洛谷P2347 砝码称重

2018-09-18 06:25:27来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

题目


 

  • 貌似是某年提高组签到题,六重循环零压力AC,差点怒踩std
  • 但本蒟蒻决定写正解——多重背包,果断20分
  • 原因是写错了状态转移方程。。。神才知道我咋过的样例和两个测试点
  • 扯远了

多重背包

  • 简单说一下多重背包
  • 限制某一些物体个数的背包
  • 可以参考fengzw的背包问题:0-1背包、完全背包和多重背包
  • 这里只说一下二进制拆分
  • 我们要保证可以选出一个物品的所有可能数量
  • 若它有n个,那么从20开始,一直到?log2n?中,每次以2k分为一组
  • 剩下的n-?log2n?单独为一组即可
  • 可以证明这种方法正确,在此不再赘述
  • 然后就是一个愉快的01背包

 

 

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 bool dp[10005];
 6 
 7 int a,weight[7]={0,1,2,3,5,10,20},tot,v[10005],ans; 
 8 
 9 inline int read(void){
10     int x=0,f=1;char ch=getchar();
11     while(ch<'0'||ch>'9'){
12         if(ch=='-') f=-1;
13         ch=getchar();
14     }
15     while(ch>='0'&&ch<='9'){
16         x=(x<<1)+(x<<3)+ch-'0';
17         ch=getchar();
18     }
19     return x*f;
20 }
21 
22 void cf(int x,int y){
23     for(register int i=1;x-i>=0;i<<=1)
24         v[++tot]=weight[y]*i,x-=i;
25     if(x) v[++tot]=weight[y]*x;
26 }
27 
28 int main(){
29     for(register int i=1;i<=6;i++)
30         a=read(),cf(a,i);
31     dp[0]=1;
32     for(register int i=1;i<=tot;i++)
33         for(register int j=10000-v[i];j>=0;j--)
34             dp[j+v[i]]|=dp[j];
35     for(register int i=1;i<=10000;i++)
36         if(dp[i]) ans++;
37     printf("Total=%d\n",ans);
38     return 0;
39 }

 

毕竟是一个可行性背包大水题,愉快地A了!

 

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:矩阵快速幂小结

下一篇:HDU6312 Game (多校第二场1004) 简单博弈