目录
题目概述:
AC代码:
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 30
#define maxv 20000
int v[maxn + 1];
int dp[maxn + 1][maxv + 1];//dp[i][j]表示前i个物品在j容量内能占去的最大空间
int main()
{
std::ios::sync_with_stdio(false);
int V, n;
cin >> V >> n;
for (int i = 1; i <= n; ++i)
cin >> v[i];
for (int i = 1; i <= n; ++i)
{
for (int j = 0; j <= V; ++j)
{
if(j<v[i])
dp[i][j]=dp[i-1][j];
else
dp[i][j] = max(dp[i-1][j],dp[i - 1][j-v[i]] +v[i]);
}
}
cout << V-dp[n][V];
return 0;
}
分析思路:
其实本质还是一道01背包问题,dp的定义已经在注释行中给出,每次选择就两种:
1.容不下当前那个了,只能不选。
2.容得下,那么在选和不选中选出最优解,在这里用max完成。
最后答案输出,注意题目问的是剩余最小空间而不是占用掉的空间。
拓展部分
非常尴尬的是第一次做题目的时候理解成每个物品都可以选择若干个,做成了完全背包问题。。不过也不是坏事,这里顺便贴上如果这题问题改成每个物品都可以选择若干个的答案代码:
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 30
#define maxv 20000
int v[maxn + 1];
int dp[maxn + 1][maxv + 1];//dp[i][j]表示前i个物品在j容量内能占去的最大空间
int main()
{
std::ios::sync_with_stdio(false);
int V, n;
cin >> V >> n;
for (int i = 1; i <= n; ++i)
cin >> v[i];
for (int i = 1; i <= n; ++i)
{
for (int j = 0; j <= V; ++j)
{
int ans = -1;
for (int k = 0; k*v[i] <= j; ++k)
{
ans = max(ans, dp[i - 1][j - k * v[i]] + k * v[i]);
}
dp[i][j] = ans;
}
}
cout << V-dp[n][V];
return 0;
}
相比较01背包问题添加了内层循环k来控制个数。