题目
总时间限制: 1000ms 内存限制: 65536kB
描述
设有1g、2g、3g、5g、10g、20g的砝码各若干枚(其总重<=1000),要求:计算用这些砝码能称出的不同重量的个数,但不包括一个砝码也不用的情况。
输入
一行,包括六个正整数a1,a2,a3,a4,a5,a6,表示1g砝码有a1个,2g砝码有a2个,……,20g砝码有a6个。相邻两个整数之间用单个空格隔开。
输出
以“Total=N”的形式输出,其中N为可以称出的不同重量的个数。
样例输入
1 1 0 0 0 0
样例输出
Total=3
提示
样例给出的砝码可以称出1g,2g,3g三种不同的重量。
分析
状态转移方程是:dp[i][j] = dp[i-1][j] || dp[i-1][j-w[i]], i表示第i个砝码,意思是把所有砝码排开计数,j表示j重量,dp[i][j]表示使用前i个砝码是否可以称出重量j,1表示可以,0表示不可以。
然后可以用滚动数组节省空间,dp[j] = 1 ,当dp[j-w[i]] =1。
代码
#include <cstdio>
#include <cstring>
int weight[6] = {1, 2, 3, 5, 10, 20};
int num[6];
int dp[1000];
int main(){
for(int i = 0; i < 6; i++){
scanf("%d", &num[i]);
}
int total = 0;
for(int i = 0; i < 6; i++){
total += weight[i] * num[i];
}
memset(dp, 0, sizeof(dp));
dp[0] = 1;
for(int i = 0; i < 6; i++){
for(int j = 0; j < num[i]; j++){
for(int k = total; k >= weight[i]; k --){
if(dp[k - weight[i]] == 1)
dp[k] = 1;
}
}
}
int sum = 0;
for(int i = 1; i <= total; i++){
if(dp[i] == 1)
sum++;
}
printf("Total=%d
", sum);
return 0;
}