动态规划法改进:用序偶法求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、结果截图
相关文章推荐
- 二叉查找(排序)树
- Linux 搜狗输入法安装
- (1)异步复位信号的同步化
- Java学习笔记
- Centos6、7 PHP5.4 5.5 5.6安装
- idea:pom导入包报错
- Android逆向之旅---基于对so中的section加密技术实现so加固
- double list
- LCA 算法之tarjan 和 并查集
- iOS之关灯小游戏
- centos7&openstack_kilo完全离线快速allinone和multi-nodes部署
- bzoj 1503 [NOI2004]郁闷的出纳员 平衡树(treap/Splay)
- 【数据挖掘】关联规则和Apriori算法
- jQuery学习笔记(二)——css与节点操作
- 无线权威指南
- 子网掩码
- 字节数组byte[]与16进制字符串的相互转化
- android中的回调
- 《老码识途》学习笔记1——c语言逆向基础
- js 文件恢复 window 解析器默认打开