完全背包问题

来源:互联网 发布:轻食食谱软件 编辑:程序博客网 时间:2024/05/16 15:54

情景预设:
完全背包是在i件物品取出若干件放在空间为j的背包里,第i件物品的重量为t[i],与之相对应的价值为v[i]。
完全背包的约束条件是给定几种物品,每种物品有无数个。
在完全背包问题中,因为每种物品有无数个,对于每个物只需要考虑放几个的情况。

这个情境下的题目要求是:选取哪些物品并且确定噶书可以在不超过背包最大承载质量下满足最大的价值要求。


由上一篇的01背包中的顺序中的BUG知道:如果顺序放入的话,后面就会出现重复放入的情况,重复的个数可以是无限个,这恰好利用最大化价值满足了完全背包的条件。

方程如下:
dp[i][v] = max{ dp[i-1][v-k*t[i]] + k*v[i] | 0 <= k*t[i]<=v}
方程表示的是在dp[i-1][v-k*t[i]] + k*v[i]中价值满足最大的k取到的最大价值。


让我假设现在的背包的容量是C=10;
物品编号: 1 2 3
物品重量: 5 6 4
物品价值:20 10 12

分析过程:
dp:0 0 0 0 0 0 0 0 0 0

i=1:
dp[5] = max(dp[0]+20, dp[5]);
dp[6] = max(dp[1]+20, dp[6]);
dp[7] = max(dp[2]+20, dp[7]);
dp[8] = max(dp[3]+20, dp[8]);
dp[9] = max(dp[4]+20, dp[9]);
dp[10] = max(dp[5]+20, dp[10]);
小于5的放不进去,5到10的全都放进去了。
dp:0 0 0 0 20 20 20 20 20 40

i=2:
dp[6] = max(dp[0]+10, dp[6]);
dp[7] = max(dp[1]+10, dp[7]);
dp[8] = max(dp[2]+10, dp[8]);
dp[9] = max(dp[3]+10, dp[9]);
dp[10] = max(dp[4]+10, dp[10]);
重复操作。
dp:0 0 0 0 20 20 20 20 20 40

i=3;
dp[4] = max(dp[0]+12, dp[4]);
dp[5] = max(dp[1]+12, dp[5]);
dp[6] = max(dp[2]+12, dp[6]);
dp[7] = max(dp[3]+12, dp[7]);
dp[8] = max(dp[4]+12, dp[8]);
dp[9] = max(dp[5]+12, dp[9]);
dp[10] = max(dp[6]+12, dp[10]);
重复操作。
dp:0 0 0 12 20 20 20 20 32 40


例题如下:
SDNU-OJ-1043
http://www.acmicpc.sdnu.edu.cn/problem/show/1043

Description
XXX上山去采药。XXX有一个容量为m(1<=m<=1000)的背包,他所采集的药材的总重量不能大于背包的容量。已知共有n(1<=n<=1000 )种药材,每种药材都有无限多,并且知道每种药材的重量w(1<=w<=m)及价值v(1<=v<=100000),如何选择,才能使得采到的药材的总价值最大?

Input
第1行为两个整数m和n,分别为背包的容量及药材的种数。 第2至n+1行每行两个整数w和v,分别表示每种药材的重量及价值。

Output
能采到的药材的最大总价值

Sample Input
100 5
77 92
33 50
34 60
50 46
99 161

Sample Output
161

关键代码如下:

for(int i = 0; i < m; i++){    for(int j = t[i]; j <= time; j++)    {         if(j >= t[i])         {               dp[j] = max(dp[j - t[i]] + v[i], dp[j]);         }    }}

完整代码:

#include <cstdio>#include <cmath>#include <iostream>using namespace std;int main(){    int time, m;    while(scanf("%d %d", &time, &m) != EOF)    {        int t[1005], v[1005];        int dp[1005]={};        for(int i = 0; i < m; i++)        {            scanf("%d %d", &t[i], &v[i]);        }        for(int i = 0; i < m; i++)        {            for(int j = t[i]; j <= time; j++)            {                if(j >= t[i])                {                    dp[j] = max(dp[j - t[i]] + v[i], dp[j]);                }            }        }        cout << dp[time] << endl;    }    return 0;}
原创粉丝点击