背包经典问题

acwing423采药

#include<iostream>
#include<stack>
#include<string.h>
#include<algorithm>
#include<sstream>
using namespace std;

int w[1010];
int cost[1010];
int dp[1010][1010];
int main(){
	int t;
	int m;
	for( int i=1;i<=n;i++){
		cin>>cost[i];
		cin>>w[i];
	}
	for( int i=1;i<=m;i++){
		for( int j=t;j>=cost[i];j--){
			dp[i][j]=max(dp[i][j],dp[i][j-cost[i]]+w[i]);
		}
	}
	cout<<dp[m][t];
}

acwing1024/《信息学奥赛一本通》装箱问题

#include<bits/stdc++.h>
using namespace std;
int a[101];
int dp[20010];
int main(){
    int v;
    int n;
    cin>>v>>n;
    for( int i=1;i<=n;i++){
        cin>>a[i];
    }
    for( int i=1;i<=n;i++){
        for( int j=v;j>=a[i];j--){
            if(dp[j-a[i]]+a[i]<=v)
            dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
        }
    }
    cout<<v-dp[v];
}

acwing1022

#include<iostream>
#include<stack>
#include<string.h>
#include<algorithm>
#include<sstream>
using namespace std;
int cos1[1010];
int cos2[1010];
int dp[1010][1010];
int main(){
	int n,m,k;
	cin>>n>>m>>k;
	for( int i=1;i<=k;i++){
		cin>>cos1[i]>>cos2[i];
	}
	for( int i=1;i<=k;i++){
		for( int j=n;j>=cos1[i];j--){
			for( int t=m;t>cos2[i];t--){
				dp[j][t]=max(dp[j][t],dp[j-cos1[i]][t-cos2[i]]+1);
			}
		}
	}
	cout<<dp[n][m]<<" ";
	if(dp[n][m]==0) {
		cout<<m;
		return 0;
	}
	for( int i=m;i>=0;i--){
		if(dp[n][i]!=dp[n][i-1]){
			cout<<m-i+1;
			break;
		}
	}
}

acwing 278/《算法竞赛进阶指南》数字组合

#include<bits/stdc++.h>
using namespace std;
int a[110];
int dp[10010];
int main(){
    int n,m;
    cin>>n>>m;
    for( int i=1;i<=n;i++){
        cin>>a[i];
    }
    dp[0]=1;
    for( int i=1;i<=n;i++){
        for( int j=m;j>=a[i];j--){
            dp[j]+=dp[j-a[i]];      
        }
    }
    cout<<dp[m];
}

acwing 1023/《信息学奥赛一本通》买书问题

#include<bits/stdc++.h>
using namespace std;
int a[110];
int dp[10010];
int main(){
    int n,m;
    cin>>n>>m;
    for( int i=1;i<=n;i++){
        cin>>a[i];
    }
    dp[0]=1;
    for( int i=1;i<=n;i++){
        for( int j=m;j>=a[i];j--){
            dp[j]+=dp[j-a[i]];      
        }
    }
    cout<<dp[m];
}

acwing 1021/《信息学奥赛一本通》货币系统

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m;
int a[20];
ll dp[3010];
int main(){
    cin>>n>>m;
    for( int i=1;i<=n;i++){
        cin>>a[i];
    }
    dp[0]=1;
    for( int i=1;i<=n;i++){
        for( int j=a[i];j<=m;j++){
            dp[j]+=dp[j-a[i]];
        }
    }
    cout<<dp[m];
}

acwing 532/noip提高组 货币系统

#include<bits/stdc++.h>
using namespace std;
int t,n;
int a[110];
int dp[25100];
int main(){
    cin>>t;
    while(t--){
        cin>>n;
        memset(dp,0,sizeof(dp));
        for( int i=1;i<=n;i++){
            cin>>a[i];
        }
        sort(a+1,a+1+n);
        int ans=0;
        dp[0]=1;
        for( int i=1;i<=n;i++){
            if(dp[a[i]]==0) {
                ans++;
                dp[a[i]]=1;
            }
            for( int j=a[i];j<=a[n];j++){
                dp[j]+=dp[j-a[i]];
            }
        }
        cout<<ans<<endl;
    }
}

acwing 1019/《信息学奥赛一本通》庆功会
二进制优化

#include<bits/stdc++.h>
using namespace std;
#define N 510
#define M 6010
int cost1[N],w1[N],s[N];
int m,n;
int cost[M],w[M];
int cnt=1;
int dp[6010];
int main(){
    cin>>n>>m;
    for( int i=1;i<=n;i++){
        cin>>cost1[i]>>w1[i]>>s[i];
        int num=1;
        while(num<=s[i]){
            cost[cnt]=num*cost1[i];
            w[cnt++]=num*w1[i];
            s[i]-=num;
            num*=2;
        }
        if(s[i]){
            cost[cnt]=s[i]*cost1[i];
            w[cnt++]=s[i]*w1[i];
        }
    }
    for( int i=1;i<cnt;i++){
        for( int j=m;j>=cost[i];j--){
            dp[j]=max(dp[j],dp[j-cost[i]]+w[i]);
        }
    }
    cout<<dp[m]<<endl;
}

acwing 7 混合背包问题

#include<bits/stdc++.h>
using namespace std;
#define N 1010
#define M 10010
int n,v;
int w[M],cost[M],type[M],cnt=1;
int dp[N];
int main(){
    cin>>n>>v;
    for( int i=1;i<=n;i++){
        int a,b,c;
        cin>>a>>b>>c;
        if(c==-1||c==0){
            cost[cnt]=a;
            w[cnt]=b;
            type[cnt++]=c;
        }
        else {
            int num=1;
            while(num<=c){
                cost[cnt]=a*num;
                w[cnt]=b*num;
                type[cnt++]=-1;
                c-=num;
                num*=2;
                
            }
            if(c){
                cost[cnt]=c*a;
                w[cnt]=b*c;
                type[cnt++]=-1;
            }
        }
    }
    for( int i=1;i<cnt;i++){
        if(type[i]==-1){
            for( int j=v;j>=cost[i];j--){
                dp[j]=max(dp[j],dp[j-cost[i]]+w[i]);
            }
        }
        else{
            for( int j=cost[i];j<=v;j++){
                dp[j]=max(dp[j],dp[j-cost[i]]+w[i]);
            }
        }
    }
    cout<<dp[v]<<endl;
}

acwing 8 二位费用背包问题

#include<bits/stdc++.h>
using namespace std;
#define N 1010
#define M 110
int n,v,m;
int cost1[N],cost2[N],w[N];
int dp[N][N];
int main(){
    cin>>n>>v>>m;
    for( int i=1;i<=n;i++){
        cin>>cost1[i]>>cost2[i]>>w[i];
    }
    for( int i=1;i<=n;i++){
        for( int  j=v;j>=cost1[i];j--){
            for( int t=m;t>=cost2[i];t--){
                dp[j][t]=max(dp[j][t],dp[j-cost1[i]][t-cost2[i]]+w[i]);
            }
        }
    }
    cout<<dp[v][m]<<endl;
}

acwing 10 有依赖的背包问题

使用dfs自上而下dfs
首先算出在没有加入根节点时树的最大价值,然后加入根节点。

#include<bits/stdc++.h>
using namespace std;
#define N 110
int w[N],to[N],ne[N],h[N],cost[N];
int cnt,n,v;
int dp[N][N];//第一层枚举节点,第二层枚举容量
void add(int a,int b){
    to[cnt]=b;ne[cnt]=h[a],h[a]=cnt++;
}
void dfs(int rt){
    if(cost[rt]>v) return;
    for( int i=h[rt];i!=-1;i=ne[i]){
        int j=to[i];
        dfs(j);
    } 
    for( int i=h[rt];i!=-1;i=ne[i]){
        int son=to[i];
        for( int j=v-cost[rt];j>=0;j--){//枚举容量
            for( int d=0;d<=j;d++)
                dp[rt][j]=max(dp[rt][j],dp[rt][j-d]+dp[son][d]);
        }
    }
    for( int i=v;i>=cost[rt];i--) dp[rt][i]=dp[rt][i-cost[rt]]+w[rt];
    for( int i=0;i<cost[rt];i++) dp[rt][i]=0;
    return ;
}
int main(){
    memset(h,-1,sizeof(h));
    cin>>n>>v;
    int root;
    for( int i=1;i<=n;i++){
        int c;
        cin>>cost[i]>>w[i]>>c;
        if(c==-1){
            root=i;
            continue;
        }
        add( c , i );
    }
    dfs(root);
    // cout<<dp[2][5]<<endl;
    cout<<dp[root][v];
    return 0;
}

acwing 11
求解背包问题最优解的方法数
开一个和dp数组平行的cnt数组,记录方法数

#include<bits/stdc++.h>
using namespace std;
#define N 1010
#define ll long long
const ll mol =1e9+7;
int w[N],cost[N];
int dp[N];
ll cnt[N];
int n,v;
int main(){
    cin>>n>>v;
    for( int i=1;i<=n;i++){
        cin>>cost[i]>>w[i];
        cnt[i]=1;
    }
    cnt[0]=1;
    //注意这里需要把所有的cnt都赋值为1
    for( int i=1;i<=n;i++){
        for( int j=v;j>=cost[i];j--){
            if(dp[j]<dp[j-cost[i]]+w[i]){
                dp[j]=dp[j-cost[i]]+w[i];
                cnt[j]=cnt[j-cost[i]]%mol;
            }//当新状态大于原状态,将原状态用新状态的cnt替换
            else if(dp[j]==dp[j-cost[i]]+w[i]){
                cnt[j]+=cnt[j-cost[i]]%mol;
            }//当新状态等于原状态,将原状态加上新状态的cnt
        }
    }
    cout<<cnt[v]%mol;
}

背包问题求具体方案
对应最短路问题求具体路径。
字典序最小直接贪心即可
dp数组可以看成一棵决策树,一共有三种决策(当可选可不选时,则必选)
若f(i,j)==f(i+1,v-cost[i])则必须选
若f(i,j)!=f(i+1,v-cost[i])则一定不选
求解背包问题的具体方案不能使用状态压缩的方式

#include <bits/stdc++.h>
using namespace std;
#define N 1010
int n,v;
int w[N],cost[N];
int dp[N][N];
int main(){
    cin>>n>>v;
    for( int i=1;i<=n;i++){
        cin>>cost[i]>>w[i];
    }
    for( int i=n;i>=1;i--){
        for( int j=v;j>=0;j--){
        	//这里注意非状态压缩背包的写法,j要从0开始循环
            if(j>=cost[i])
            dp[i][j]=max(dp[i+1][j],dp[i+1][j-cost[i]]+w[i]);
            else 
            dp[i][j]=dp[i+1][j];
        }
    }
    int vv=v;
    for(int i=1;i<=n;i++){
    //注意不要越界
        if(vv>=cost[i]&&dp[i][vv]==dp[i+1][vv-cost[i]]+w[i]){
            vv-=cost[i];
            cout<<i<<" ";
        }
        else{
            continue;
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值