Time Limit: 10 second
Memory Limit: 2 MB
问题描述
设有1g,2g,3g,5g,10g,20g的砝码各若干枚(其总重≦1000g),要求:
Input
a1 a2 a3 a4 a5 a6(表示1g砝码有a1个,2g砝码有a2个,......20g砝码有a6个Output
Total=n(n表示用这些砝码能称出不同重量的个数,但不包括一个砝码也不用的情况,注意第一个T是大写的)
Sample Input
1 1 0 0 0 0
Sample Output
Total=3
Sample Input1
0 3 2 7 4 5
Sample Output1
Total=185
【题解】
可以看成6个物品,6个物品的多重背包问题。
然后按照多重背包的更新顺序,来确定某一个值是否能达到。
一开始can[0] = true;
然后if (can[j-w[i]*k)
can[j] = true;
因为只要再拿k个i砝码就能够组合成J了。
w[]数组的1..6的值是固定的就是1,2,3,5,10,20
只要注意更新的顺序就可以了,不会很难。
最后从1-1000扫描一遍if (can[i]) tot++;
【代码】
#include <cstdio> #include <cstring> const int w[7] = {0,1,2,3,5,10,20}; int num[7],tot = 0; bool can[1010]; void input_data() { for (int i = 1; i <= 6;i++) scanf("%d",&num[i]); } void get_ans() { memset(can,false,sizeof(can)); can[0] = true; for (int i = 1;i <= 6;i++) //枚举6个物品 for (int j = 1010;j >= 0;j--) //枚举最大容量 (就是数字的最大值,题目有说不大于1000) for (int k = 1;k <= num[i];k++)// 枚举该物品的使用数量 { if (j - w[i]*k < 0) continue; if (can[j-w[i]*k]) //如果j-w[i]*k这个重量可以达到。那么j这个重量也可以达到! can[j] = true; } for (int i = 1;i <= 1000;i++) if (can[i]) tot++; } void output_ans() { printf("Total=%d",tot); } int main() { //freopen("F:\rush.txt","r",stdin); input_data(); get_ans(); output_ans(); return 0; }