动态规划 0--1 背包问题

给定一个物品集合s={1,2,3,…,n},物品i的重量是wi,其价值是vi,背包的容量为W,即最大载重量不超过W。在限定的总重量W内,我们如何选择物品,才能使得物品的总价值最大。

如果物品不能被分割,即物品i要么整个地选取,要么不选取;

不能将物品i装入背包多次,也不能只装入部分物品i,则该问题称为0—1背包问题。

如果物品可以拆分,则问题称为背包问题,适合使用贪心算法

给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问:应如何选择装入背包的物品,使得装入背包中物品的总价值最大?

设(y1,y2,…,yn)是 (3.4.1)的一个最优解.则(y2,…,yn)是下面相应子问题的一个最优解:

证明:使用反证法。若不然,设(z2,z3,…,zn)是上述子问题的一个最优解,而(y2,y3,…,yn)不是它的最优解。显然有                                     ∑vizi > ∑viyi   (i=2,…,n)      且                           w1y1+ ∑wizi<= c      因此                       v1y1+ ∑vizi (i=2,…,n) > ∑ viyi, (i=1,…,n)      说明(y1,z2, z3,…,zn)是(3.4.1)0-1背包问题的一个更优解,导出(y1,y2,…,yn)不是背包问题的最优解,矛盾。

递推关系:

设所给0-1背包问题的子问题

的最优值为m(i,j),即m(i,j)是背包容量为j,可选择物品为i,i+1,…,n时0-1背包问题的最优值。由0-1背包问题的最优子结构性质,可以建立计算m(i,j)的递归式:

注:(3.4.3)式此时背包容量为j,可选择物品为i。此时在对xi作出决策之后,问题处于两种状态之一:     (1)背包剩余容量是j,没产生任何效益;     (2)剩余容量j-wi,效益值增长了vi ; (3) 对于最后一个物品n , 如果 j>=Wn,则肯定装入, 获得价值Vn; 如果0<=j < Wn,则无法装入, 获得的价值为 0 。

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4
 5 #define NUM 50              //物品数量的上界
 6 #define CAP 1500            //背包容量的上界
 7 int v[NUM];                 //物品的重量
 8 int w[NUM];                 //物品的价值
 9 int p[NUM][CAP];            //用于递归的数组。
10 //形参 c 是背包的容量 W,n是物品的数量。
11 void knapsack(int c, int n)
12 {
13     //计算递推边界
14     int jMax=min(w[n]-1,c);   //分界点。
15     for( int j=0; j<=jMax; j++)
16         p[n][j]=0;
17     for( int j=w[n]; j<=c; j++)
18         p[n][j]=v[n];
19     for( int i=n-1; i>1; i--)//计算递推式
20     {
21         jMax=min(w[i]-1,c);
22         for( int j=0; j<=jMax; j++)
23             p[i][j]=p[i+1][j];
24         for(int j=w[i]; j<=c; j++)
25             p[i][j]=max(p[i+1][j], p[i+1][j-w[i]]+v[i]);
26     }
27     p[1][c]=p[2][c];         //计算最优值。
28     if (c>=w[1])
29         p[1][c]=max(p[1][c], p[2][c-w[1]]+v[1]);
30 }
31 //形参数组 x 是解向量。
32 void traceback( int c, int n, int x[])
33 {
34     for(int i=1; i<n; i++)
35     {
36         if (p[i][c]==p[i+1][c]) x[i]=0;
37         else { x[i]=1; c-=w[i]; }
38     }
39     x[n]= (p[n][c]) ? 1:0;
40 }
41
42 int main ()
43 {
44     int x[NUM];
45     int W;
46     int n;
47     while (scanf("%d", &W) && W)
48     {
49         scanf("%d", &n);
50         for (int i=1; i<=n; i++)
51             scanf("%d%d", &w[i], &v[i]);
52         memset (p, 0, sizeof(p));
53         knapsack(W, n);
54         printf("%d\n", p[1][W]);
55         traceback(W, n, x);
56         for (int i=1; i<=n; i++)
57             if (x[i]) printf("%d ", i);
58         printf("\n");
59     }
60     return 0;
61 }

时间: 2024-11-06 07:42:48

动态规划 0--1 背包问题的相关文章

动态规划0—1背包问题

动态规划0-1背包问题 ? 问题描写叙述: 给定n种物品和一背包.物品i的重量是wi,其价值为vi,背包的容量为C.问应怎样选择装入背包的物品,使得装 入背包中物品的总价值最大? ? 对于一种物品,要么装入背包,要么不装.所以对于一种物品的装入状态能够取0和1.我们设物品i的装入状态为xi,xi∈ (0,1),此问题称为0-11背包问题. 过程分析 数据:物品个数n=5,物品重量w[n]={0,2,2,6,5,4},物品价值V[n]={0,6,3,5,4,6}, (第0位,置为0,不參与计算,仅

动态规划--0,1背包问题(再也不怕类似背包问题了)

这种类型问题三大要素:总重量.每件物品重量.每件物品价值,问最终能够塞进背包中的价值最大是多少?应该怎么选择物品? 当然也不一定是这些,例如上节所说的矿工挖矿:总人数.挖每座矿的人数.每座矿的金子数. 也就是说,只要出现了这三大要素,都可以视为0,1背包问题(物品不可拆分) 动态规划三要素:边界.最优子结构.状态转移方程. 我们一步步进行解析: 初始化:物品总重量:c=8,物品类别:n=['a','b','c','d'],物品重量:w=[2,4,5,3],物品价值:v=[5,4,6,2] 假设我

动态规划算法实现部分——0/1背包问题

代码: import java.util.*; import java.util.Scanner; /* *动态规划思想解决0/1背包问题 */ public class Main{ public static void main(String[] args){ Scanner in=new Scanner(System.in); System.out.println("输入背包的容量"); int bagCap=in.nextInt(); //背包的容量 System.out.pri

动态规划算法求解0,1背包问题

首先我们来看看动态规划的四个步骤: 1. 找出最优解的性质,并且刻画其结构特性: 2. 递归的定义最优解: 3. 以自底向上的方式刻画最优值: 4. 根据计算最优值时候得到的信息,构造最优解 其中改进的动态规划算法:备忘录法,是以自顶向下的方式刻画最优值,对于动态规划方法和备忘录方法,两者的使用情况如下: 一般来讲,当一个问题的所有子问题都至少要解一次时,使用动态规划算法比使用备忘录方法好.此时,动态规划算法没有任何多余的计算.同时,对于许多问题,常常可以利用其规则的表格存取方式,减少动态规划算

[转载]动态规划之0-1背包问题

作者:Hawstein出处:http://hawstein.com/posts/dp-knapsack.html 一切都要从一则故事说起. 话说有一哥们去森林里玩发现了一堆宝石,他数了数,一共有n个. 但他身上能装宝石的就只有一个背包,背包的容量为C.这哥们把n个宝石排成一排并编上号: 0,1,2,-,n-1.第i个宝石对应的体积和价值分别为V[i]和W[i] .排好后这哥们开始思考: 背包总共也就只能装下体积为C的东西,那我要装下哪些宝石才能让我获得最大的利益呢? OK,如果是你,你会怎么做?

【动态规划】简单背包问题II

问题 B: [动态规划]简单背包问题II 时间限制: 1 Sec  内存限制: 64 MB提交: 21  解决: 14[提交][状态][讨论版] 题目描述 张琪曼:“为什么背包一定要完全装满呢?尽可能多装不就行了吗?” 李旭琳:“你说得对,这和墨老师曾告诉我们的‘日中则昃,月满则亏’是一个道理.”所以,现在的问题是,她们有一个背包容量为v(正整数,0≤v≤20000),同时有n个魔法石(0≤n≤30),每个魔法石有一个体积 (正整数).要求从n个魔法石中,任取若干个装入包内,使背包的剩余空间为最

【动态规划】完全背包问题

贵有恒,何必三更起五更眠:最无益,莫过一日曝十日寒. [动态规划]完全背包问题 时间限制: 1 Sec  内存限制: 64 MB 题目描述 话说张琪曼和李旭琳又发现了一处魔法石矿(运气怎么这么好?各种嫉妒羡慕恨啊),她们有一个最多能装m公斤的背包,现在有n种魔法石,每种的重量分别是W1,W2,…,Wn,每种的价值分别为C1,C2,…,Cn.若每种魔法石的个数足够多,求她们能获得的最大总价值. 输入 第一行为两个整数,即m,n. 以后每行为两个整数,表示每块魔法石的重量和价值. 输出 获得的最大总

动态规划解决0-1背包问题

这几天算法老师布置了一个作业是关于背包问题的,在这里记录一下解决的过程: 一:背包问题的描述 有n1,n2,n3....个物品,每个物品的重量为w1,w2,w3.....,每个物品的价值为v1,v2,v3....,现在有一个承重量为C的背包,求出要怎样放物品才能使的装入背包的物品价值总和最大.由于每个物品只有一个,并且只能选择放或不放,因此用0表示物体没有放进背包中,1表示物体放进背包中 二:分析过程(以具体的例题来分析) 题目描述: 现有一个可以承重为6的背包bag,以及3个物品,它们的重量分

求解0/1背包问题

动态规划 //求解0_1背包问题 //动态规划 #include<stdio.h> #define MaxN 20 #define MaxW 100 int knap(int f[MaxN][MaxW],int w[],int v[],int W,int n){ //动态规划求数组f[][] int i,r; for(i=0;i<=n;i++) f[i][0] = 0; for(r=0;r<=W;r++) f[0][r] = 0; for(i=1;i<=n;i++){ for

背包问题:0/1背包问题 普通背包问题(贪心算法只适用于普通背包问题)

//sj和vj分别为第j项物品的体积和价值,W是总体积限制. //V[i,j]表示从前i项{u1,u2,…,un}中取出来的装入体积为j的背包的物品的最大价值. 第一种:0/1背包问题 最大化 ,受限于  1)若i=0或j=0,  V[i,j] = 0 2)若j<si, V[i,j] = V[i-1,j] 3)若i>0且j>=si, V[i,j] = Max{V[i-1,j],V[i-1,j-si]+vi} 第二种:背包问题:在选择物品i装入背包时,可以选择物品i的一部分,而不一定要全部