您的位置:首页 > 其它

动态规划之背包问题

2016-10-15 13:42 274 查看

动态规划之背包问题

问题:给定n个物品,每个物品都有重量和价值,现在希望选择一个物品子集使得总重量小于给定的重量并且总价值最大。问题如下图所示:



分析: 可以把问题的求解过程看成是一系列的决策过程,在第i步,我们决定i个物品是否装。现在假装我们得到子问题的最优解,当前考虑最后一个物品是装还是不装。如果装,则原问题变成从前n−1个物品中选择限重W−Wn的物品子集使得价值最大。如果不装,则问题变成在前n−1件物品中选择限重为W的物品子集使得价值最大。我们定义opt[i,w]为前i件物品中限重w的最大价值。此时,我们可以总结出递归表达式如下:

OPT[i,w]=maxOPT[i−1,w],OPT[i−1,w−wi]+valuei

具体实现过程如下:

/*********************************************
IDE:Dev c++5.11
Data:2016.10.15
Author:Robert.Tianyi
**********************************************/
#include<stdio.h>
#include<stdlib.h>
struct goods{
int price;
int w;
};
int max(int a,int b){
return a>b?a:b;
}
int Knapsack_DP(struct goods Goods[],int n){
int max_w=15;
int (*opt)[max_w+1];
int i,w,wi;
opt=(int (*)[max_w+1])malloc(sizeof(int)*(n+1)*(max_w+1));
for(i=0;i<=n;i++)
for(w=0;w<=max_w;w++)
opt[i][w]=0;
for(i=1;i<=n;i++){
for(w=1;w<=max_w;w++){
opt[i][w]=opt[i-1][w];
if(w-Goods[i].w>=0){
opt[i][w]=max( opt[i-1][w],opt[i-1][w-Goods[i].w]+Goods[i].price );
}
}
}
printf("最大重量:w ");
for(w=0;w<=max_w;w++)
printf("%4d",w);
printf("\n");
for(i=0;i<=n;i++){
printf("前%d件物品:",i);
for(w=0;w<=15;w++){
printf("%4d",opt[i][w]);
}
printf("\n");
}
return opt
[15];
}
void main(){
int value;
struct goods Goods[6];
Goods[0].price=0;Goods[0].w=0;
Goods[1].price=10;Goods[1].w=9;
Goods[2].price=7;Goods[2].w=12;
Goods[3].price=1;Goods[3].w=2;
Goods[4].price=3;Goods[4].w=7;
Goods[5].price=2;Goods[5].w=5;
value=Knapsack_DP(Goods,5);
printf("max_price=%d",value);
}


运行结果如下:



总结:本问题有nW个子问题,每个子问题做两次比较,所以时复杂度为O(nW)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: