题目描述
知识点
完全背包+充满背包
实现
码前思考
- 其实完全背包的思想我理解的还不够,先这样吧,把模板记下来,后面看能不能通过一些方式理解。
代码实现
//使用完全背包问题,注意这里要充满背包,而且还是求最小值,不是最大值
#include "bits/stdc++.h"
using namespace std;
//设置无限大
const int INF = 0x3fffffff;
//w的限制
const int maxw =10010;
//货币的限制
const int maxn = 510;
//Test case的数量
int T;
//货币种类数
int n;
//价值数组
int p[maxn];
//重量数组
int w[maxw];
//dp数组,我们使用1维的数组
int dp[maxw];
int main(){
scanf("%d",&T);
while(T--){
int a,b;
scanf("%d %d",&a,&b);
//最大的重量
int W = b-a;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d %d",&p[i],&w[i]);
}
//对dp数组进行初始化
//由于要充满整个背包才行
//所以初始化条件有些不一样
dp[0] = 0;
//只有0,0是0,其他的都是正无穷代表当前不满足情况!!!只要看其代表意思即可,不要管他这么大
for(int j=1;j<=W;j++){
dp[j] = INF;
}
//进行dp,注意是充满背包,而且是求最小值
for(int i=1;i<=n;i++){
//注意是顺序的,不是逆序的
for(int j=w[i];j<=W;j++){
dp[j] = min(dp[j],dp[j-w[i]]+p[i]);
}
}
if(dp[W] < INF){
printf("The minimum amount of money in the piggy-bank is %d.\n",dp[W]);
}else{
printf("This is impossible.\n");
}
}
return 0;
}
码后反思
- 特别注意题目的隐性要求是要充满整个背包!
- 理解一维的
dp
数组的含义。 - 下面这个更好理解充满的含义:
......
//对dp数组进行初始化
//由于要充满整个背包才行
//所以初始化条件有些不一样
dp[0] = 0;
//只有0,0是0,其他的都是正无穷代表当前不满足情况!!!只要看其代表意思即可,不要管他这么大
for(int j=1;j<=W;j++){
dp[j] = INF;
}
//进行dp,注意是充满背包,而且是求最小值
for(int i=1;i<=n;i++){
//注意是顺序的,不是逆序的
for(int j=w[i];j<=W;j++){
if(dp[j] == INF && dp[j-w[i]]==INF){
dp[j] = INF;
}else{
dp[j] = min(dp[j],dp[j-w[i]]+p[i]);
}
}
}
.......
}