背包问题

需要灵活地01背包知识点题目链接
需要灵活地01背包知识点题目链接

01背包问题:

给定n件物品,每件物品的重量为w[i],价值为c[i]。现挑选若干物品放入背包中,假定背包能承受的重量为V,问应该如何选择装入背包的物品,使得能装入背包的物品总价值最大?
如果按照常规(暴力)方法解决,对于每一件物品,你都有选或不选的权力,那么就有2^n种组合,显然这个方法一般情况下不可行。
解决01背包问题,主要靠动态规划的思想。
每个动态规划问题都是从一个网格开始。动态规划是从子问题着手,逐步解决大的问题
传送门,biu~

01背包基础题目及代码
小P寻宝记——粗心的基友
Description

这对好基友他们在经历无数的艰难险阻后,终于找到了宝藏。无奈的是这一对好基友竟然是一样的粗心,又忘记了带一个大一点的包包,可惜啊、、选择又出现了啊、、
已知包的体积是v,每种宝贝只有一个,宝贝的体积是pi,价值是wi。求出这对粗心的基友可以最多带走价值多少的宝藏。
Input

输入数据有多组。
每组第一行有两个正整数n(n <= 10000)和v(v <= 10000)分别表示n种宝贝和包的体积。
接下来n行,每行有两个正整数vi, wi。
分别表示每种宝藏的体积vi (vi<=1000),价值wi(wi<=1000)。
Output

这对基友所能带走的最多的宝藏。
Sample

Input

5 10
1 5
2 4
3 3
4 2
5 1
Output

14
ac代码:

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

int main()
{
    int n,v;
    while(cin>>n>>v)
    {
       int vi[10001],wi[10001];

       int i;
       for(i=1;i<=n;i++)
       {
          cin>>vi[i]>>wi[i];
       }
       int dp[10001];
       memset(dp,0,sizeof(dp));
       //01背包的优化
       //未优化dp[i][j]=max(dp[i-1][j],dp[i-1[j-v[i]]]+w[i]);但此题必须优化;
       for(i=1;i<=n;i++)
       {
          for(int j=v;j>=vi[i];j--)
          {
             dp[j]=max(dp[j],dp[j-vi[i]]+wi[i]);
             
          }
       }
       printf("%d\n",dp[v]);
    }
    return 0;
}

完全背包问题

有n种物品和一个容量为V的背包,物品体积为v[i],价值为w[i],物品可以选无数次,问题:选哪些物品放进背包,使得物品总价值最大,且不超过背包总容量
对于完全背包问题,dp[i][j]=max⁡{dp[i−1][j−k∗w[i]]+k∗v[i]∣0≤k&k∗w[i]≤j}
传送门,biu~
经过数学推导得到公式:dp[i][j]=max{dp[i-1][j],dp[i][j-v[i]]+w[i]}
小P寻宝记——好基友一起走
Description

话说,上次小P到伊利哇呀国旅行得到了一批宝藏。他是相当开心啊,回来就告诉了他的好基友小鑫,于是他们又结伴去伊利哇呀国寻宝。
这次小P的寻宝之路可没有那么的轻松,他们走到了一个森林,小鑫一不小心被触发了机关,被困在了一个大笼子里面,笼子旁边上有一道题目和一个密码锁,上面说只要解出此题输入密码即可救出被困人。小鑫不是很聪明,所以他做不出来,他知道小P很笨,更解不出来。所以他就让小P独自回去,不用管他。但是小P重情重义不会抛弃他离去。他说:“不,好基友一起走!”。于是就感动了上帝,上帝特派你来替他们解决问题。聪明的你要加油了啊!
题目描述:给你n种物品和一个体积为v的包包。每种物品有无数种,体积是vi价值是wi。求出包包v所能装的最大价值的东西。
Input

多组输入。第一行有两个正整数n(0<n<=10000), v(0<v<= 10000)。接下来两行每行有n个数字。第一行表示每种物品的价值wi(0<wi<100),第二行表示每种物品的体积vi(0<vi<100)。
Output

输出最多可以得到的价值。输出结果救出小鑫。
Sample

Input

5 20
1 2 3 4 5
2 6 3 5 4
Output

25
ac代码:

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

using namespace std;
int dp[10001],vi[10001],wi[10001];
int main()
{
    int n,V;
    while(cin>>n>>V)
    {
        for(int i=1;i<=n;i++)
        {
            cin>>wi[i];
        }
        for(int i=1;i<=n;i++)
        {
            cin>>vi[i];
        }
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
        {
            for(int j=vi[i];j<=V;j++)
            {
                dp[j]=max(dp[j],dp[j-vi[i]]+wi[i]);
            }
        }
        cout<<dp[V]<<endl;
    }
    return 0;
}

多重背包

有N种物品和一个容量为T的背包,第i种物品最多有M[i]件可用,价值为w[i],体积为v[i],求解:选哪些物品放入背包,可以使得这些物品的价值最大,并且体积总和不超过背包容量
对比完全背包,其实就是多了一个限制条件
在多重背包这里,物品数量具有一定的限制
对于之前的完全背包问题,k>=0&kv[i]<=j,这里的多重背包的限制条件就变成了0<=k<=m[i]&&kv[i]<=j
多重背包:dp[i][j]=max⁡{dp[i−1][j−k∗w[i]]+k∗v[i]∣0≤k<=m[i]&&k∗w[i]≤j}
可以将多重背包问题拆成01背包问题来做,时间复杂度为O(T*M[i])

int main() {
    int n, m;//n代表
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> w[i] >> v[i] >> num[i];
    }
    int k = n + 1;
    for (int i = 1; i <= n; i++) {
        while (num[i] != 1) {
            w[k] = w[i];
            v[k] = v[i];
            k++;
            num[i]--;
        }
    }
    cin >> m;
    for (int i = 1; i <= k; i++) {
        for (int j = m; j >= 1; j--) {
            if (w[i] <= j) dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
        }
    }
    cout <<dp[m] << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值