题目描述
设有1g1g1g、2g2g2g、3g3g3g、5g5g5g、10g10g10g、20g20g20g的砝码各若干枚(其总重≤1000 le 1000≤1000),
输入输出格式
输入格式:
输入方式:a1,a2,a3,a4,a5,a6a_1 , a_2 ,a_3 , a_4 , a_5 ,a_6a1,a2,a3,a4,a5,a6
(表示1g1g1g砝码有a1a_1a1个,2g2g2g砝码有a2a_2a2个,…,20g20g20g砝码有a6a_6a6个)
输出格式:
输出方式:Total=NTotal=NTotal=N
(NNN表示用这些砝码能称出的不同重量的个数,但不包括一个砝码也不用的情况)
这道题类似于“小A点菜”那道题,都是01背包求方案数
都是先将f[0]=1,然后f[j]+=f[j-c[i]]计算
即
设f[i][j]为体积为i的方案总和
那么,当第i件物品不选时,f[i][j]=f[i-1][j]
那么如果选择了呢,f[i][j]=f[i-c[i]];
那么两者累加,就是f[i][j]=f[i-1][j]+f[i-c[i]]
为了减少空间浪费,去掉第一维,可以得到:
f[i]=f[i]+f[i-c[i]],也就是f[i]+=f[i-c[i]]
最后再扫一遍记录个数
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; #define maxn 100010 #define clear(a) memset(a,0,sizeof a) #define ll long long #define IL inline IL void read(int &x) { x = 0;int f = 1;char ch = getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f = -f;ch = getchar();} while(ch>='0'&&ch<='9'){x = x * 10 + ch - '0', ch = getchar();}x *= f; } int tot, sum, ans; int pre[7] = {0, 1, 2, 3, 5, 10, 20}; int a[10], f[maxn], val[maxn]; int main() { for (int i = 1; i <= 6;i++) { read(a[i]); sum += a[i]*pre[i]; } f[0] = 1; for (int i = 1; i <= 6;i++) for (int j = 1;j<=a[i];j++) val[++tot] = pre[i]; for (int i = 1; i <= tot;i++) for (int j = sum; j >= val[i];j--) f[j] += f[j - val[i]]; for (int i = 1; i <= sum;i++) if(f[i]) ans++;//如果某一位为true说明可能出现这种情况 cout << "Total=" << ans; return 0; }