背包九讲代码总结

代码模板总结:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 1000005;
ll dp[maxn];
ll cost[maxn], weight[maxn], amount[maxn];
ll n, v;
void ZeroOnePack(ll cost, ll weight) {
    for (ll j = v; j >= cost; --j)//逆序枚举
        dp[j] = max(dp[j], dp[j - cost] + weight);//保证第i次循环中的状态f[i][j]是由状态f[i−1][j−w[i]]递推而来
}
void CompletePack(ll cost, ll weight) {
    for (ll j = cost; j <= v; ++j)//顺序枚举
        dp[j] = max(dp[j], dp[j - cost] + weight);
}
void MultiplePack(ll cost, ll weight, ll amount) {
    if (cost * amount >= v) {//此时相当于物品数量无限进行完全背包
        CompletePack(cost, weight);
    }
    else {
        for (ll k = 1; k <= amount; k <<= 1) {//二进制拆分
            ZeroOnePack(cost * k, weight * k);
            amount -= k;//将物品减去
        }
        ZeroOnePack(amount * cost, amount * weight);
    }
}

01背包:

题目

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 100005;
const ll MOD = 1e9 + 7;
const ll INF = 0x7fffffff;
ll dp[maxn];
ll cost[maxn], weight[maxn];
ll n, v;
int main() {
    ios_base::sync_with_stdio(false), cin.tie(0);
    cin>>n>>v;
    for(int i=1;i<=n;i++)cin>>cost[i]>>weight[i];
    
	for(int i=1;i<=n;i++){
	    for (ll j = v; j >= cost[i]; j--){//逆序枚举
	        dp[j] = max(dp[j], dp[j - cost[i]] + weight[i]);//保证第i次循环中的状态f[i][j]是由状态f[i−1][j−w[i]]递推而来
	    }
	}
    cout<<dp[v]<<"\n";
    return 0;

}

完全背包:

总体积不超过背包容量:题目

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 100005;
const ll MOD = 1e9 + 7;
const ll INF = 0x7fffffff;
ll dp[maxn];
ll cost[maxn], weight[maxn];
ll n, v;
void CompletePack(ll cost, ll weight) {
    
}
int main() {
    ios_base::sync_with_stdio(false), cin.tie(0);
    cin>>n>>v;
    for(int i=1;i<=n;i++)cin>>cost[i]>>weight[i];
    
    for(int i=1;i<=n;i++){
	    for (ll j = cost[i]; j <= v; j++){//顺序枚举
	        dp[j] = max(dp[j], dp[j - cost[i]] + weight[i]);
	    }
    }
    cout<<dp[v]<<"\n";
    return 0;

}

多重背包:

题目一
朴素算法

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 100005;
const ll MOD = 1e9 + 7;
const ll INF = 0x7fffffff;
ll dp[maxn];
ll cost[maxn], weight[maxn], amount[maxn];
ll n, v;
int main() {
    ios_base::sync_with_stdio(false), cin.tie(0);
    cin>>n>>v;
    for (ll i = 1; i <= n; ++ i)cin >> cost[i] >> weight[i] >> amount[i];
    
    for (ll i = 1; i <= n; ++ i) {
        for (ll j = v; j >= cost[i]; -- j) 
            for (ll k = 0; k <= amount[i] && k * cost[i] <= j; ++ k) 
                dp[j] = max(dp[j], dp[j - k * cost[i]] + k * weight[i]);
    }
    
    cout << dp[v]<<"\n";
    return 0;

}

题目二
二进制优化

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 1000005;
const ll MOD = 1e9 + 7;
const ll INF = 0x7fffffff;
ll dp[maxn];
ll cost[maxn], weight[maxn], amount[maxn];
ll n, v;
void ZeroOnePack(ll cost, ll weight) {
    for (ll j = v; j >= cost; --j)//逆序枚举
        dp[j] = max(dp[j], dp[j - cost] + weight);//保证第i次循环中的状态f[i][j]是由状态f[i−1][j−w[i]]递推而来
}
void CompletePack(ll cost, ll weight) {
    for (ll j = cost; j <= v; ++j)//顺序枚举
        dp[j] = max(dp[j], dp[j - cost] + weight);
}
void MultiplePack(ll cost, ll weight, ll amount) {
    if (cost * amount >= v) {//此时相当于物品数量无限进行完全背包
        CompletePack(cost, weight);
    }
    else {
        for (ll k = 1; k <= amount; k <<= 1) {//二进制拆分
            ZeroOnePack(cost * k, weight * k);
            amount -= k;//将物品减去
        }
        ZeroOnePack(amount * cost, amount * weight);
    }
}
int main() {
    ios_base::sync_with_stdio(false), cin.tie(0);
    cin>>n>>v;
    for (int i = 1; i <= n; ++i)cin >> cost[i]>>weight[i]>>amount[i];
    for (int i = 1; i <= n; ++i)MultiplePack(cost[i], weight[i], amount[i]);
    cout << dp[v]<<"\n";
    return 0;

}

题目三
单调队列优化

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 100005;
const ll MOD = 1e9 + 7;
const ll INF = 0x7fffffff;
ll dp[maxn];
ll cost[maxn], weight[maxn], amount[maxn];
ll ans[maxn];
ll n, v;
struct node {
    ll pos, val;
}q[maxn];
int main() {
    ios_base::sync_with_stdio(false), cin.tie(0);
    cin >> n >> v;
    for (ll i = 1; i <= n; i++)cin >> cost[i] >> weight[i] >> amount[i];

    for (ll i = 1; i <= n; i++){
        for (ll j = 0; j < cost[i]; j++) {

            ll hh = 0, tt = 0, stop = (v - j) / cost[i];
            for (ll k = 0; k <= stop; ++k) {
                ll val = dp[k * cost[i] + j] - k * weight[i];
                
                while (hh < tt && val >= q[tt - 1].val) --tt;
                q[tt].pos = k, q[tt++].val = val;
                if (q[hh].pos < k - amount[i]) ++hh;
                
                dp[cost[i] * k + j] = q[hh].val + k * weight[i];
            }

        }
    }
    cout<<dp[v];
    return 0;
}

二维费用背包:

题目

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 1005;
const ll MOD = 1e9 + 7;
const ll INF = 0x7fffffff;
ll dp[maxn][maxn];
ll cost1[maxn], weight[maxn], cost2[maxn];
ll n, v, m;
int main() {
    ios_base::sync_with_stdio(false), cin.tie(0);
    cin >> n >> v >> m;
    for (int i = 1; i <= n; i++)cin >> cost1[i] >> cost2[i] >> weight[i];

    for (int i = 1; i <= n; i++) {
        
        for (int j = v; j >= cost1[i]; j--) {
            for (int k = m; k >= cost2[i]; k--) {
                dp[j][k] = max(dp[j][k], dp[j - cost1[i]][k - cost2[i]] + weight[i]);
            }
        }
        
    }
    
    cout << dp[v][m];
    return 0;

}

分组背包:

题目一

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 1005;
const ll MOD = 1e9 + 7;
const ll INF = 0x7fffffff;
ll dp[maxn];
ll cost[maxn][maxn], weight[maxn][maxn];
ll n, v;
int main() {
    ios_base::sync_with_stdio(false), cin.tie(0);
    cin >> n >> v;
    ll num[maxn];
    for (ll i = 1; i <= n; i++) {
        cin >> num[i];
        for (ll j = 1; j <= num[i]; j++) {
            cin >> cost[i][j] >> weight[i][j];
        }
    }

    for(ll i=1;i<=n;i++)
        for(ll j=v;j>=0;j--)
            for(ll k=1;k<=num[i];k++)
                if(j>=cost[i][k])dp[j]=max(dp[j],dp[j-cost[i][k]]+weight[i][k]);
    cout << dp[v];
    return 0;

}

题目二

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 1005;
const ll MOD = 1e9 + 7;
const ll INF = 0x7fffffff;
ll dp[maxn];
ll cost[maxn][maxn], weight[maxn][maxn];
ll n, v;
int main() {
    ios_base::sync_with_stdio(false), cin.tie(0);
    cin >> v >> n;
    vector<ll> gruop[maxn];
    set<ll> gruop_num;
    for (ll i = 1; i <= n; i++) {
        ll c, w, g;
        cin >> c >> w>> g;
        gruop[g].push_back(g);
        gruop_num.insert(g);
        cost[g][gruop[g].size()] = c;
        weight[g][gruop[g].size()] = w;
    }

    for (ll i = 1; i <= gruop_num.size(); i++)
        for (ll j = v; j >= 0; j--)
            for (ll k = 1; k <= gruop[i].size(); k++)
                if (j >= cost[i][k])dp[j] = max(dp[j], dp[j - cost[i][k]] + weight[i][k]);
    cout << dp[v];
    return 0;

}

背包问题求总方案数:

0/1背包求方案数:总体积不超过背包容量:题目

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 1005;
const ll MOD = 1e9 + 7;
const ll INF = 0x7fffffff;
ll dp[maxn];
ll cost[maxn], weight[maxn];
ll ans[maxn];
ll n, v;
int main() {
    ios_base::sync_with_stdio(false), cin.tie(0);
    cin >> n >> v;
    for (ll i = 1; i <= n; i++) cin >> cost[i] >> weight[i];
    for (ll i = 0; i <= v; i++)ans[i] = 1;
    for (int i = 1; i <= n; i++) {
        for (ll j = v; j >= cost[i]; j--) {
            ll left = dp[j], right = dp[j - cost[i]] + weight[i];
            dp[j] = max(left, right);
            if (left > right)ans[j] = ans[j];
            else if (left < right)ans[j] = ans[j - cost[i]];
            else ans[j] = ans[j] + ans[j - cost[i]];
            ans[j] %= MOD;
        }
    }
    cout<<ans[v];
    return 0;

}

0/1背包求方案数:总体积恰好为背包容量题目

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 1005;
const ll MOD = 1e9 + 7;
const ll INF = 0x7fffffff;
ll dp[maxn];
ll cost[maxn];
ll ans[maxn];
ll n, v;
int main() {
    ios_base::sync_with_stdio(false), cin.tie(0);
    cin >> n >> v;
    for (ll i = 1; i <= n; i++) cin >> cost[i];//每个物体的花费
    dp[0]=1;//初始为1
    for (int i = 1; i <= n; i++) {//遍历每个物品
        for (ll j = v; j >= cost[i]; j--) {
            dp[j] += dp[j - cost[i]];
        }
    }
    cout << dp[v];
    return 0;

}

完全背包求方案数:总体积恰好为背包容量题目
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 4005;
const ll MOD = 2147483648;
const ll INF = 0x7fffffff;
ll dp[N];
ll n;
int main() {
    ios_base::sync_with_stdio(false), cin.tie(0);
    cin >> n ;
    dp[0]=1;//初始为1
    for (ll i = 1; i < n; i++) {
        for (ll j = i; j <= n; j++) {
            dp[j] = (dp[j]+dp[j - i])%MOD;//保证从最开始转移到最后
        }
    }
    cout << dp[n] << "\n";
    return 0;

}

背包问题求具体方案:

题目

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 1005;
const ll MOD = 1e9 + 7;
const ll INF = 0x7fffffff;
ll dp[maxn][maxn];
ll cost[maxn], weight[maxn];
ll n, v;
int main() {
    ios_base::sync_with_stdio(false), cin.tie(0);
    cin >> n >> v;
    for (ll i = 1; i <= n; i++) cin >> cost[i] >> weight[i];

    for (ll i = n; i >= 1; i--) {
        for (ll j = 0; j <= v; j++) {
            dp[i][j] = dp[i + 1][j];
            if (cost[i] <= j) dp[i][j] = max(dp[i][j], dp[i + 1][j - cost[i]] + weight[i]);
        }
    }

    ll temp = v;
    for (ll i = 1; i <= n; i++) {//如果是最后一个元素,特判一下,防止越界即可
        if (i == n && temp >= cost[i]) {
            cout << i << " ";
            break;
        }
        if (temp <= 0)break;
        //判断下标是否越界
        if (temp - cost[i] >= 0 && dp[i][temp] == dp[i + 1][temp - cost[i]] + weight[i]) {
            cout << i << " ";
            temp = temp - cost[i];//选了第i个物品,剩余容量就要减小。
        }
    }
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值