您的位置:首页 > 其它

动态规划法改进:用序偶法求0/1背包问题

2015-11-21 12:06 316 查看

动态规划法改进:用序偶法求0/1背包问题

1、问题



2、方法







3、实现代码

////序偶法求0/1背包问题(动态规划法改进版)
//// by 孙琨SealSun at UCAS
//// 2015.11.20
#include<iostream>
using namespace std;
#define MAX 256

void Knapsack(int n,int c,int v[],int w[],int p[][MAX],int x[]); // 求最优值
void Traceback(int n,int w[],int v[],int p[][MAX],int *head,int x[]); // 求最优解

void Knapsack(int n,int c,int v[],int w[],int p[][MAX],int x[]){
int *head = new int[n+2];
head[n+1] = 0;
p[0][0] = 0;
p[0][1] = 0;
int left = 0,right = 0,next = 1;
head
= 1;
for(int i=n; i>=1; i--){ // 整体
int k = left;
for(int j=left; j<=right; j++){ // 某一段
if(p[j][0]+w[i]>c){
break;
}
int y = p[j][0]+w[i];
int m = p[j][1]+v[i];
while(k<=right && p[k][0]<y){ // 平整段
p[next][0] = p[k][0];
p[next++][1] = p[k++][1];
}
if(k<=right && p[k][0]==y){ // 跃升点
if(m<p[k][1]){
m = p[k][1];
}
k++;
}
if(m>p[next-1][1]){
p[next][0] = y;
p[next++][1] = m;
}
while(k<=right && p[k][1]<=p[next-1][1]){
k++;
}
}
while(k<=right){
p[next][0] = p[k][0];
p[next++][1] = p[k++][1];
}
left = right+1;
right = next-1;
head[i-1] = next;
}
Traceback(n,w,v,p,head,x);
cout << "最大物品价值为:" <<endl;
cout << p[next-1][1]<<endl;
}

void Traceback(int n,int w[],int v[],int p[][MAX],int *head,int x[]){
int j = p[head[0]-1][0];
int m = p[head[0]-1][1];
for(int i=1; i<=n; i++){
x[i] = 0;
for(int k=head[i+1];k<=head[i]-1;k++){
if(p[k][0]+w[i]==j && p[k][1]+v[i]==m){ // 若值已存入,则此代表物品已被选中,选中为1
x[i] = 1;
j = p[k][0];
m = p[k][1];
break;
}
}
}
cout << "选中的物品是:"<<endl;
cout << "第" ;
for(int i=1; i<=n; i++){
if(x[i] == 1){
cout << i << " ";
}
}
cout << "件物品" << endl;
}

// 测试用例
int main(){
int n; // 物品数
int c; // 背包容量
int w[MAX]; // 各物品的重量
int v[MAX]; // 各物品的价值
int p[MAX][MAX]={0}; // 保存的当前最大价值,p[][1]为当前最优值
int x[MAX]={0}; // 最优解
cout << "请输入背包的最大容量:"<<endl;
cin >> c;
cout << "请输入物品的个数:"<<endl;
cin >> n;
cout << "请分别输入物品的重量:"<<endl;
for(int i=1; i<=n; i++){
cin >> w[i];
}
cout << "请分别输入物品的价值:"<<endl;
for(int i=1; i<=n;i++){
cin >> v[i];
}
Knapsack(n,c,v,w,p,x);
return 0;
}


4、结果截图

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