https://cn.vjudge.net/problem/HDU-1114
题意:
给定一个储蓄罐可容纳的重量和n个价值为p重量为w的硬币,问在填满储蓄罐的情况最小的价值为多少?
如果没办法填满输出This is impossible.
weight(w花费) value (v价值)
一般的背包是达到尽可能大的价值。
变形:小:初始化:将dp[0]=0,其他的都初始化为无穷大即可。
在求dp的时候,要将max改为min.状态转移方程:dp[j]=Min(dp[j],dp[j-weight[i]]+value[i]);
分析:01背包更新状态时从V(背包的容积)开始更新。 而完全背包则可以直接从当前物品v[i]开始更新。
原因是完全背包的特点恰是每种物品可选无限件,所以在考虑“加选一件第i种物品”这种策略时,需要一个可能已选入第i种物品的子结果f[i][v-c[i]],所以就可以并且必须采用v=0..V的顺序循环。
#include<iostream>
#include<string.h>
#include<algorithm>
#define INF 100000000
using namespace std;
//给定一个储蓄罐可容纳的重量V=f-e
//n个价值为p 重量为w的硬币
//dp[i]花费为i时的最小价值
int dp[10002];
int v[502];
int w[502];
int n;
int main(){
int t;
cin>>t;//t个测试案例
while(t--){
int e,f;//e空罐子的重量 f满罐子的重量
//.........输入
cin>>e>>f;
cin>>n;//n个价值为v 花费为w的硬币
for(int i=1;i<=n;++i){
cin>>v[i]>>w[i];
}
//...........初始化
for(int i=0;i<=f-e;++i){
dp[i]=INF;
}
dp[0]=0;
//完全背包,每件物品有无数件 (转化为01背包)
for(int i=1;i<=n;++i){
for(int j=w[i];j<=f-e;++j){//顺序
dp[j]=min(dp[j],dp[j-w[i]]+v[i]);
}
}
if(dp[f-e]!=INF)
cout<<"The minimum amount of money in the piggy-bank is "<<dp[f-e]<<"."<<endl;
else
cout<<"This is impossible."<<endl;
}
return 0;
}
模板
#include<iostream>
#include<string.h>
#include<algorithm>
#define INF 100000000
using namespace std;
//dp[i]花费为i时的最小价值
int dp[10002];
int v[502];
int w[502];
int n;
int main(){
int t;
cin>>t;
while(t--){
int e,f;
cin>>e>>f;
cin>>n;
for(int i=1;i<=n;++i){
cin>>v[i]>>w[i];
}
for(int i=0;i<=f-e;++i){
dp[i]=INF;
}
dp[0]=0;
//完全背包,每件物品有无数件 (转化为01背包)
for(int i=1;i<=n;++i){
for(int j=w[i];j<=f-e;++j){//顺序
dp[j]=min(dp[j],dp[j-w[i]]+v[i]);
}
}
if(dp[f-e]!=INF)
cout<<"The minimum amount of money in the piggy-bank is "<<dp[f-e]<<"."<<endl;
else
cout<<"This is impossible."<<endl;
}
return 0;
}