dp[j]表示硬币可以凑成和为j的钱数。
如果dp[j - num[i]]可以凑成,那么dp[j]肯定可以凑成,加上硬币面值为num[i]就可以了。
第二重for循环需要逆推,这保证了一个硬币只能选择一次。
这题加深了我对01背包使用一维数组实现的理解。讲解移步这里。
#include <iostream>
#include <cstring>
using namespace std;
const int MAX_N = 105;
const int MAX_M = MAX_N * 500;
int dp[MAX_M];
int num[MAX_N];
int n,sum;
int T;
int main()
{
cin >> T;
while(T--)
{
cin >> n;
sum = 0;
memset(dp,0,sizeof(dp));
dp[0] = 1;
for(int i = 0;i < n;i++)
{
cin >> num[i];
sum += num[i];
}
for(int i = 0;i < n;i++)
{
for(int j = sum;j - num[i]>= 0;j--)
if(dp[j - num[i]])
dp[j] = 1;
}
for(int i = sum >> 1;i >= 0;i--)
{
if(dp[i])
{
cout << sum - i * 2 << endl;
break;
}
}
}
return 0;
}
2980



被折叠的 条评论
为什么被折叠?



