题目描述
PIPI有n种硬币,每种硬币有特定的重量wei[i] 克和它对应的价值val[i].
已知有一个承重量为m的存钱罐,当里面正好装着重量为m的硬币时,问你这个存钱罐中硬币的最小价值是多少? 如果不可能存在m克的情况, 那么就输出”impossible“
输入
多组输入。
第一行包括两个整数n,m(1<=n<=500,1<=m<=10000)
接下来n行,每行两个整数v,w,表示第i中硬币的价值与重量。(1<=v<=10000,1<=w<=m)
输出
输出可能的最小价值,如果不可能存在m克的情况, 那么就输出”impossible“
样例输入
2 100
1 1
30 50
2 100
1 1
50 30
样例输出
60
100
思路:完全背包问题(最小背包)
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 1e9
/*
完全背包问题(最小背包)
明确了这个模型是完全背包问题,我们再来确定初始状态,dp数组的初始状态,dp[0]应该是0,dp[1-m]都INF,
原因是想用硬币更新其值,不然就是一个硬币都没有放入。(感觉类比求一个数组的最小值比较好理解这里的初始化INF的处理)
既然是求得最小价值,那么状态转移方程应该是dp[j]=min(dp[j-c[i]+w[i],dp[j]);
*/
const int N = 1e4+5;
int dp[N];
int main(){
int n,m;
while(~scanf("%d %d",&n,&m)){
// dp[0] = 0; //默认是0
for(int i=1;i<=m;i++){
dp[i] = INF; //初始条件
}
int v[n+1],w[n+1];
for(int i=1;i<=n;i++){
scanf("%d %d",&v[i],&w[i]);
}
for(int i=1;i<=n;i++){
//注意j是正序循环(因为每种硬币有无数个,可重复放)
for(int j=w[i];j<=m;j++){
dp[j] = min(dp[j],dp[j-w[i]]+v[i]);
}
}
if(dp[m] == INF){ //说明没有装满
printf("impossible\n");
}else{
printf("%d\n",dp[m]);
}
}
return 0;
}