您的位置:首页 > 其它

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

2015-06-18 17:18 288 查看
给定一个物品集合s={1,2,3,…,n},物品i的重量是wi,其价值是vi,背包的容量为W,即最大载重量不超过W。在限定的总重量W内,我们如何选择物品,才能使得物品的总价值最大。
如果物品不能被分割,即物品i要么整个地选取,要么不选取;
不能将物品i装入背包多次,也不能只装入部分物品i,则该问题称为0—1背包问题。
如果物品可以拆分,则问题称为背包问题,适合使用贪心算法

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

#include<iostream>
#include<cstring>
using namespace std;

#define NUM 50              //物品数量的上界
#define CAP 1500            //背包容量的上界
int v[NUM];                 //物品的重量
int w[NUM];                 //物品的价值
int p[NUM][CAP];            //用于递归的数组。
//形参 c 是背包的容量 W,n是物品的数量。
void knapsack(int c, int n)
{
//计算递推边界
int jMax=min(w
-1,c);   //分界点。
for( int j=0; j<=jMax; j++)
p
[j]=0;
for( int j=w
; j<=c; j++)
p
[j]=v
;
for( int i=n-1; i>1; i--)//计算递推式
{
jMax=min(w[i]-1,c);
for( int j=0; j<=jMax; j++)
p[i][j]=p[i+1][j];
for(int j=w[i]; j<=c; j++)
p[i][j]=max(p[i+1][j], p[i+1][j-w[i]]+v[i]);
}
p[1][c]=p[2][c];         //计算最优值。
if (c>=w[1])
p[1][c]=max(p[1][c], p[2][c-w[1]]+v[1]);
}
//形参数组 x 是解向量。
void traceback( int c, int n, int x[])
{
for(int i=1; i<n; i++)
{
if (p[i][c]==p[i+1][c]) x[i]=0;
else { x[i]=1; c-=w[i]; }
}
x
= (p
[c]) ? 1:0;
}

int main ()
{
int x[NUM];
int W;
int n;
while (scanf("%d", &W) && W)
{
scanf("%d", &n);
for (int i=1; i<=n; i++)
scanf("%d%d", &w[i], &v[i]);
memset (p, 0, sizeof(p));
knapsack(W, n);
printf("%d\n", p[1][W]);
traceback(W, n, x);
for (int i=1; i<=n; i++)
if (x[i]) printf("%d ", i);
printf("\n");
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: