题意:
给你一个容量为n的背包,和数量为m的物品,每件物品有价值和重量,并且可以取无数次,问你怎样取得最小值,并把重量取满。
思路:
一开始写了一个01背包,稍微改了一下变成完全背包了,不过被卡空间了。
然后看了一下讨论区是用完全背包写的,就去学习了一下完全背包的做法,和优化空间。
这题就是一个裸的完全背包把dp初始化inf就行了。滚动数组优化空间也挺简单的。
代码:(01背包卡空间版本)



#include<bits/stdc++.h>
using namespace std;

int n;
const int maxn = 1e4 + 10;
struct node{
    int v,w;
    node(){}
    node(int a,int b):v(a),w(b){}
}a[1100];
int dp[maxn][maxn],weight[maxn][maxn]; 
//dp[i][j]:容量为i的前j件物品的最小价值 
int main(){
    int t;cin>>t;
    while(t--){
        int e,f;cin>>e>>f;
        cin>>n;
        for(int i = 1; i <= n; i++){
            cin>>a[i].v>>a[i].w;
        }
        int m = f - e;
        memset(dp,0,sizeof(dp));
        memset(weight,0,sizeof(weight));
        for(int i = 1; i <= m; i++){
            if(i >= a[1].w){
                dp[i][1] = a[1].v + dp[i - a[1].w][1];
                weight[i][1] = weight[i - a[1].w][1] + a[1].w;
            }
        }
        for(int i = 1; i <= m ; i++){//枚举容量 
            for(int j = 2; j <= n; j++){//枚举物品 
                if(a[j].w <= i){
                    int l = dp[i][j - 1];
                    int r = dp[i - a[j].w][j] + a[j].v;
                    if(l < r){
                        dp[i][j] = l;
                        weight[i][j] = weight[i][j - 1];
                    }else{
                        dp[i][j] = r;
                        weight[i][j] = weight[i - a[j].w][j] + a[j].w;
                    }
                } else{
                    dp[i][j] = dp[i][j - 1];//这个物品不放 
                    weight[i][j] = weight[i][j - 1];
                }
            }
        }
        if(weight[m][n] == m){
            cout<<"The minimum amount of money in the piggy-bank is "<<dp[m][n]<<"."<<endl;
        }else{
            cout<<"This is impossible."<<endl;
        }
    }
}

完全背包ac版本:

#include<bits/stdc++.h>
using namespace std;

const int inf = 0x3f3f3f3f;
const int maxn = 1e4 + 10; 
int v[maxn],w[maxn]; 
int dp[maxn];
int main(){
    int t ;
    cin>>t;
    while(t--){
        int e , f;cin>>e>>f;
        int n = f - e;
        int m;cin>>m;
        for(int i = 1; i <= m; i++)cin>>v[i]>>w[i];
        memset(dp,0x3f,sizeof(dp));
        dp[0] = 0;
        for(int i = 1; i <= m; i++){
            for(int j = n; j >= 1; j--){
                for(int k = 0; k <= j/w[i]; k++){
                    dp[j] = min(dp[j],dp[j - k * w[i]] + k * v[i]);
                }
            }
        }
        if(dp[n] == inf)cout<<"This is impossible."<<endl;
        else cout<<"The minimum amount of money in the piggy-bank is "<<dp[n]<<"."<<endl; 
    }
}

最终优化版本:

#include<bits/stdc++.h>
using namespace std;

const int inf = 0x3f3f3f3f;
const int maxn = 1e4 + 10; 
int v[maxn],w[maxn]; 
int dp[maxn];
int main(){
	int t ;
	cin>>t;
	while(t--){
		int e , f;cin>>e>>f;
		int n = f - e;
		int m;cin>>m;
		for(int i = 1; i <= m; i++)cin>>v[i]>>w[i];
		memset(dp,0x3f,sizeof(dp));
		dp[0] = 0;
		for(int i = 1; i <= m; i++)
		for(int j = w[i]; j <= n; j++)
		dp[j] = min(dp[j],dp[j - w[i]] + v[i]);
		if(dp[n] == inf)cout<<"This is impossible."<<endl;
		else cout<<"The minimum amount of money in the piggy-bank is "<<dp[n]<<"."<<endl; 
	}
}