题目描述
AC Code
#include <iostream>
using namespace std;
const int maxn = 1005;
const int Lim = 200005;
int a[Lim] = {0},b[] = {0,1,2,3,5,10,20},f[maxn] = {0},cnt = 0;
int main()
{
for(int i=1;i<=6;i++){
int n;
cin>>n;
while(n --){
a[++cnt] = b[i];
}
}
f[0] = 1;
for(int i=1;i<=cnt;i++){
for(int j=maxn-1;j>=0;j--){
if(f[j]){
f[j+a[i]] = 1;
}
}
}
int ans = 0;
for(int i=1;i<maxn;i++){
if(f[i]) ans++;
}
cout<<"Total="<<ans;
return 0;
}
解释
①数据输入:由于初涉背包问题,一开始以为可以用类似于01背包的解法AC本题,故将砝码拆成一个一个,存入另一个数组当中。这一步的思路是正确的,但是本题不是背包问题,而是需要使用dp来记录之前的状态。对于初涉背包问题的学者,我认为一定要区分好背包dp和普通dp。
②虽然题目中明确提到了,不包括砝码一个不放的情况,但我们仍将f[0] = 1
视为一种情况,只不过在最后统计有哪些重量可以被称出时,忽略f[0]
。将f[0] = 1
的理由是,只有这样初始化,才能完成后面的dp任务。
③暴力:
for(int i=1;i<=cnt;i++){
for(int j=maxn-1;j>=0;j--){
if(f[j]){
f[j+a[i]] = 1;
}
}
}
双重循环,先遍历每一个砝码的重量,再遍历每一个可能取到的重量,即,根据每一个砝码的重量,去观察某一点的重量,再加上这个砝码的重量能否被称出。
④AC。