标签:
Description
Input
Output
Sample Input
3 10
1 2 4 2 1 1
2 5
1 4 2 1
0 0
Sample Output
8
4
//题意是 第一行两个整数 n 和 m (1 <= n <= 100)(m <= 100000) 然后第二行是 n 个硬币的价值,再是 n 个硬币的数量,
问这些硬币能组成多少个小于等于 m 的价值。
多重背包,有一点难吧,要用到二进制优化,直接当 0 1 背包处理要超时
hud 340ms 另一个oj 187 ms
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 using namespace std; 5 6 int a[105],c[105],d[105]; 7 bool f[100005]; 8 9 int max(int a,int b) 10 { 11 return a>b?a:b; 12 } 13 14 int main() 15 { 16 int i,j,k,m,n; 17 while(scanf("%d%d",&n,&m)&&n+m) 18 { 19 for(i=1;i<=n;i++) 20 scanf("%d",&a[i]); 21 for(i=1;i<=n;i++) 22 scanf("%d",&c[i]); 23 24 memset(f,0,sizeof(f)); 25 f[0]=1; 26 27 for(i=1;i<=n;i++) 28 { 29 if(a[i]*c[i]>=m) //如果该货币总价值大于等于 m 30 { 31 for(j=a[i];j<=m;j++) 32 if(!f[j]) //只需记得能不能达到即可 33 f[j]=f[j-a[i]]; 34 } 35 else //总价值小于 m 36 { 37 if(c[i]==0) 38 continue; 39 40 int num=c[i]; 41 int p=1; 42 int t=1; 43 44 while(p<num) //二进制优化的 0 1 背包 1 . 2 . 4 . 8 45 { 46 d[t++]=a[i]*p; 47 num-=p; 48 p*=2; 49 } 50 51 d[t++]=a[i]*num; 52 53 for(j=1;j<t;j++) 54 for(k=m;k>=d[j];k--)//f[k]=max(f[k],f[k-d[j]]); 55 { 56 if(!f[k]) 57 f[k]=f[k-d[j]]; 58 } 59 } 60 } 61 62 j=0; 63 for(i=1;i<=m;i++) 64 { 65 if(f[i]==1) 66 j++; 67 } 68 printf("%d\n",j); 69 } 70 return 0; 71 }
标签:
原文地址:http://www.cnblogs.com/haoabcd2010/p/5747408.html