0—1 背包问题 C++程序实现
0-1背包问题的多种解法

问题描述0/1 背包问题 :现有 n 种物品,对 1<=i<=n ,已知第 i 种物品的重量为正整数 W i ,价值为正整数 V i , 背包能承受的最大载重量为正整数 W ,现要求找出这 n 种物品的一个子集,使得子集中物 品的总重量不超过 W 且总价值尽量大。
(注意:这里对每种物品或者全取或者一点都不取, 不允许只取一部分)算法分析根据问题描述,可以将其转化为如下的约束条件和目标函数:nw i x i W i 1 i i(1)x i { 0,1}( 1 i n)nmax v i x i (2) i1于是,问题就归结为寻找一个满足约束条件( 1 ),并使目标函数式( 2 )达到最大的 解向量 X (x 1, x 2 ,x 3, ........... , x n ) 。
首先说明一下 0-1 背包问题拥有最优解。
假设 (x 1,x 2,x 3, ........ ,x n ) 是所给的问题的一个最优解, 则(x 2,x 3, ............... ,x n )是下面问题的n n n个问 题 的 一 个 最 优解 , 则v i y iv i x i , 且 w 1x 1w i y i W 。
因此 ,i 2 i 2 i 2一个最优解:w i x i Wi2w 1x 1nmax v i x i 。
如果不是的话,设(y 2,y 3, , y n ) 是这x i {0,1}( 2 i n)i2n n nv1x1 v i y i v1x1 v i x i v i x i ,这说明(x1,y2,y3, ............. ,y n) 是所给的0-1 背包问i 2 i 2 i 1题比( x1 , x 2 , x3 , ... , x n ) 更优的解,从而与假设矛盾。
穷举法:用穷举法解决0-1 背包问题,需要考虑给定n 个物品集合的所有子集,找出所有可能的子集(总重量不超过背包重量的子集) ,计算每个子集的总重量,然后在他们中找到价值最大的子集。
01背包问题代码

1. 0-1背包问题程序代码#include<iostream>#include<iomanip>using namespace std;int c[50][50];int w[10],v[10];int x[10];int n;int i;void KNAPSACK_DP(int n,int W){for(int k=0;k<=W;k++)c[0][k]=0;for(int i=1;i<=n;i++){ c[i][0]=0;for(int k=1;k<=W;k++){if(w[i]<=k) {if(v[i]+c[i-1][k-w[i]]>c[i-1][k])c[i][k]=v[i]+c[i-1][k-w[i]];elsec[i][k]=c[i-1][k];}elsec[i][k]=c[i-1][k];}}}void OUTPUT_SACK(int c[50][50],int k) {for(int i=n;i>=2;i--){if(c[i][k]==c[i-1][k])x[i]=0;else{x[i]=1;k=k-w[i];}}x[1]=(c[1][k]?1:0);for(i=1;i<=n;i++)cout<<setw(4)<<x[i]; }void main(){int m;cout<<"输入物品个数:";cin>>n;cout<<"依次输入物品的重量:"<<endl; for(int i=1;i<=n;i++)cin>>w[i];cout<<"依次输入物品的价值:"<<endl; for(i=1;i<=n;i++)cin>>v[i];cout<<"输入背包最大容量:";cin>>m;for(i=1;i<=m;i++)cout<<setw(4)<<i;cout<<endl;KNAPSACK_DP(n,m);cout<<"构造最优解过程如下:"<<endl; for(int j=1;j<=5;j++){for(int k=1;k<=m;k++)cout<<setw(4)<<c[j][k];cout<<endl;}cout<<"最优解为:"<<endl;OUTPUT_SACK(c,m);}2.运行结果。
经典ACM算法合集经典ACM算法合集

① 若cs>d,则为不可行解,剪去相应子树,返回到i-1层继续执行;
② 若ws>=bestw,则不是最优解,剪去相应子树,返回到i-1层继续执行;
③ 若i >n,则算法搜索到一个叶结点,用bestw对最优解进行记录,返回到
i-1层继续执行;
④ 采用for循环对部件i从m个不同的供应商购得的情况进行讨论(1≤j≤m):
2、题目分析:
考虑到每种物品只有2 种选择,即装入背包或不装入背包,并且物品数和背包容量已给定,要计算装入背包物品的最大价值和最优装入方案,可用回溯法搜索子集树的算法进行求解。
3、算法设计:
a. 物品有n种,背包容量为C,分别用p[i]和w[i]存储第i种物品的价值和重量,用
x[i]标记第i种物品是否装入背包,用bestx[i]存储第i种物品的最优装载方案;
b. 用函数cover()判断图G 是否被顶点覆盖(用t标记):
① 初始t=0;
② 采用while循环对每个顶点i(1≤i≤n)进行讨论:
1> 若顶点i不在顶点覆盖集中(即c[i]==0),则查找与之有边连接的顶点j(即e[i][j]==1),判断所有顶点j:
若存在顶点j在顶点覆盖集中(即c[j]==0),则t=1;
1> 调用递归函Knapsack(i+1,cs+c[i][j],ws+w[i][j])对部件i+1进行购买;
2> 当j>m时for循环结束;
⑤ 当i=1时,若已测试完所有购买方案,外层调用就全部结束;
c. 主函数调用一次Knapsack(1,0,0)即可完成整个回溯搜索过程,最终得到的bestw
0-1背包问题-贪心法和动态规划法求解

实验四“0-1”背包问题一、实验目的与要求熟悉C/C++语言的集成开发环境;通过本实验加深对贪心算法、动态规划算法的理解。
二、实验内容:掌握贪心算法、动态规划算法的概念和基本思想,分析并掌握“0-1”背包问题的求解方法,并分析其优缺点。
三、实验题1.“0-1”背包问题的贪心算法2.“0-1”背包问题的动态规划算法说明:背包实例采用教材P132习题六的6-1中的描述。
要求每种的算法都给出最大收益和最优解。
设有背包问题实例n=7,M=15,,(w0,w1,。
w6)=(2,3,5,7,1,4,1),物品装入背包的收益为:(p0,p1,。
,p6)=(10,5,15,7,6,18,3)。
求这一实例的最优解和最大收益。
四、实验步骤理解算法思想和问题要求;编程实现题目要求;上机输入和调试自己所编的程序;验证分析实验结果;整理出实验报告。
五、实验程序// 贪心法求解#include<iostream>#include"iomanip"using namespace std;//按照单位物品收益排序,传入参数单位物品收益,物品收益和物品重量的数组,运用冒泡排序void AvgBenefitsSort(float *arry_avgp,float *arry_p,float *arry_w ); //获取最优解方法,传入参数为物品收益数组,物品重量数组,最后装载物品最优解的数组和还可以装载物品的重量float GetBestBenifit(float*arry_p,float*arry_w,float*arry_x,float u);int main(){float w[7]={2,3,5,7,1,4,1}; //物品重量数组float p[7]={10,5,15,7,6,18,3}; //物品收益数组float avgp[7]={0}; //单位毒品的收益数组float x[7]={0}; //最后装载物品的最优解数组const float M=15; //背包所能的载重float ben=0; //最后的收益AvgBenefitsSort(avgp,p,w);ben=GetBestBenifit(p,w,x,M);cout<<endl<<ben<<endl; //输出最后的收益system("pause");return 0;}//按照单位物品收益排序,传入参数单位物品收益,物品收益和物品重量的数组,运用冒泡排序void AvgBenefitsSort(float *arry_avgp,float *arry_p,float *arry_w ) {//求出物品的单位收益for(int i=0;i<7;i++){arry_avgp[i]=arry_p[i]/arry_w[i];}cout<<endl;//把求出的单位收益排序,冒泡排序法int exchange=7;int bound=0;float temp=0;while(exchange){bound=exchange;exchange=0;for(int i=0;i<bound;i++){if(arry_avgp[i]<arry_avgp[i+1]){//交换单位收益数组temp=arry_avgp[i];arry_avgp[i]=arry_avgp[i+1];arry_avgp[i+1]=temp;//交换收益数组temp=arry_p[i];arry_p[i]=arry_p[i+1];arry_p[i+1]=temp;//交换重量数组temp=arry_w[i];arry_w[i]=arry_w[i+1];arry_w[i+1]=temp;exchange=i;}}}}//获取最优解方法,传入参数为物品收益数组,物品重量数组,最后装载物品最优解的数组和还可以装载物品的重量float GetBestBenifit(float*arry_p,float*arry_w,float*arry_x,float u) {int i=0; //循环变量ifloat benifit=0; //最后收益while(i<7){if(u-arry_w[i]>0){arry_x[i]=arry_w[i]; //把当前物品重量缴入最优解数组benifit+=arry_p[i]; //收益增加当前物品收益u-=arry_w[i]; //背包还能载重量减去当前物品重量cout<<arry_x[i]<<" "; //输出最优解}i++;}return benifit; //返回最后收益}//动态规划法求解#include<stdio.h>#include<math.h>#define n 6void DKNAP(int p[],int w[],int M,const int m); void main(){int p[n+1],w[n+1];int M,i,j;int m=1;for(i=1;i<=n;i++){m=m*2;printf("\nin put the weight and the p:");scanf("%d %d",&w[i],&p[i]);}printf("%d",m);printf("\n in put the max weight M:");scanf("%d",&M);DKNAP(p,w,M,m);}void DKNAP(int p[],int w[],int M,const int m) {int p2[m],w2[m],pp,ww,px;int F[n+1],pk,q,k,l,h,u,i,j,next,max,s[n+1];F[0]=1;p2[1]=w2[1]=0;l=h=1;F[1]=next=2;for(i=1;i<n;i++){k=l;max=0;u=l;for(q=l;q<=h;q++)if((w2[q]+w[i]<=M)&&max<=w2[q]+w[i]){u=q;max=w2[q]+w[i];}for(j=l;j<=u;j++){pp=p2[j]+p[i];ww=w2[j]+w[i];while(k<=h&&w2[k]<ww){p2[next]=p2[k];w2[next]=w2[k];next++;k++;}if(k<=h&&w2[k]==ww){if(pp<=p2[k])pp=p2[k];k++;}else if(pp>p2[next-1]){p2[next]=pp;w2[next]=ww;next++;}while(k<=h&&p2[k]<=p2[next-1])k++;}while(k<=h){p2[next]=p2[k];w2[next]=w2[k];next=next+1;k++;}l=h+1;h=next-1;F[i+1]=next;}for(i=1;i<next;i++)printf("%2d%2d ",p2[i],w2[i]);for(i=n;i>0;i--){next=F[i];next--;pp=pk=p2[next];ww=w2[next];while(ww+w[i]>M&&next>F[i-1]){next=next-1;pp=p2[next];ww=w2[next];}if(ww+w[i]<=M&&next>F[i-1])px=pp+p[i];if(px>pk&&ww+w[i]<=M){s[i]=1;M=M-w[i];printf("M=%d ",M);}else s[i]=0;}for(i=1;i<=n;i++)printf("%2d ",s[i]);}六、实验结果1、贪心法截图:七、实验分析。
山东科技大学2018年算法设计与分析考试题真题

yi=divide—and-conquer (Pi); return merge(y1, ..., yk);
背包问题与01背包问题类似所不同的是在选择物品i装入背包时可以选择物品i的一部分而不一定要全部装入背包用贪心算法解背包问题的贪心策略
一、简答题(1题4分,2题4分,3题6分,共14分)
1。什么是算法?什么是程序?。
2。算法的特点是什么? 3。给出算法复杂度计量符号 O和 的定义.
二、算法复杂度计算 (10分)
一、简答题(1题4分,2题4分,3题6分,共14分)
1。算法是指解决问题的一种方法或一个过程。………………………………………【2分】 程序是算法用某种程序设计语言的具体实现………………………………………【2分】
2.算法的特点: (1)确定性:算法的每一种运算必须有确切的定义,无二义性。…………………【1分】 (2)有限性:算法中每条指令的执行次数、每条指令的执行时间都是有限的。…【1分】 (3)输入:有 0个或者多个输入。………………………………………………………【1分】 (4)输出:有 1个或者多个输出。………………………………………………………【1分】 3.算法复杂度计量符号 O和 的定义:
n
max vixi
i2
n
wixi c
w1x1,
i2
xi {0,1},2 i n
否则,设(z2, …, zn)是最优解,则(y1, z2, …, zn)是原问题的更优解,而(y1, y2, …, yn)
C语言动态规划之背包问题详解

C语⾔动态规划之背包问题详解01背包问题给定n种物品,和⼀个容量为C的背包,物品i的重量是w[i],其价值为v[i]。
问如何选择装⼊背包的物品,使得装⼊背包中的总价值最⼤?(⾯对每个武平,只能有选择拿取或者不拿两种选择,不能选择装⼊某物品的⼀部分,也不能装⼊物品多次)声明⼀个数组f[n][c]的⼆维数组,f[i][j]表⽰在⾯对第i件物品,且背包容量为j时所能获得的最⼤价值。
根据题⽬要求进⾏打表查找相关的边界和规律根据打表列写相关的状态转移⽅程⽤程序实现状态转移⽅程真题演练:⼀个旅⾏者有⼀个最多能装M公⽄的背包,现在有n件物品,它们的重量分别是W1、W2、W3、W4、…、Wn。
它们的价值分别是C1、C3、C2、…、Cn,求旅⾏者能获得最⼤价值。
输⼊描述:第⼀⾏:两个整数,M(背包容量,M<= 200)和N(物品数量,N<=30);第2…N+1⾏:每⾏两个整数Wi,Ci,表⽰每个物品的质量与价值。
输出描述:仅⼀⾏,⼀个数,表⽰最⼤总价值样例:输⼊:10 42 13 34 57 9输出:12解题步骤定义⼀个数组dp[i][j]表⽰容量为j时,拿第i个物品时所能获取的最⼤价值。
按照题⽬要求进⾏打表,列出对应的dp表。
W[i](质量)V[i](价值)01234567891000000000000210011111111133001334444444500135568899790013556991012对于⼀个动态规划问题设置下标时最好从0开始,因为动态规划经常会和上⼀个状态有关系!从上⾯的dp表可以看出来对于⼀个物品我们拿还是不难需要进⾏两步来判断。
第⼀步:判断背包当前的容量j是否⼤于物品当前的质量,如果物品的质量⼤于背包的容量那么就舍弃。
第⼆步:如果背包可以装下这个物品,就需要判断装下该物品获取的最⼤价值是不是⼤于不装下这个物品所获取的最⼤价值,如果⼤于那么就把东西装下!根据这样的思想我们可以得到状态转移⽅程:如果单签背包的容量可以装下物品:dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);如果当前背包的容量装不下该物品:dp[i][j]=dp[i-1][j];#include <stdio.h>int max(const int a,const int b){return a>b ? a:b;}int main(){int w[35]={0},v[35]={0},dp[35][210]={0};int n,m;scanf("%d %d",&m,&n);int i,j;for(i=1;i<=n;i++){scanf("%d %d",&w[i],&v[i]);}for(i=1;i<=n;i++){for(j=1;j<=m;j++){if(j>=w[i])//如果当前背包的容量⼤于商品的质量{dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);//判断是否应该拿下}else//⼤于背包的当前容量{dp[i][j]=dp[i-1][j];}}}for(int k=0;k<=n;k++){for(int l=0;l<=m;l++){printf("%d ",dp[k][l]);}printf("\n");}printf("%d\n",dp[n][m]);}通过运⾏以上程序可以看到最终的输出dp表和我们的预期是相符合的!但是并没有结束,动态规划有⼀个后⽆效性原则(当前状态只与前⼀个状态有关)。
国家集训队2009论文集浅谈几类背包题

浅谈几类背包题浙江省温州中学徐持衡指导老师:舒春平2008年12月目录摘要 (3)关键字 (3)正文 (4)一、引言 (4)二、背包的基本变换 (5)①完全背包 (5)②多次背包 (5)③单调队列优化☆ (6)三、其他几类背包问题 (8)①树形依赖背包(获取学分)☆ (8)②PKU3093☆ (11)四、总结 (12)附录 (13)参考文献 (13)文中原题 (13)摘要背包问题作为一个经典问题在动态规划中是很基础的一个部分,然而以0-1背包问题为原题,衍生转变出的各类题目,可以说是千变万化,当然解法也各有不同,如此就有了继续探究的价值。
本文就4道背包变化的题做一些探讨研究,提出本人的一些做法,希望能起到抛砖引玉的作用。
关键字动态规划背包优化正文一、引言背包问题是运筹学中的一个经典的优化难题,是一个NP-完全问题,但其有着广泛的实际应用背景,是从生活中一个常见的问题出发展开的:一个背包,和很多件物品,要在背包中放一些物品,以达到一定的目标。
在信息学中,把所有的数据都量化处理后,得到这样的一个问题:0-1 背包问题:给定n 件物品和一个背包。
物品i的价值是W i,其体积为V i,背包的容量为C。
可以任意选择装入背包中的物品,求装入背包中物品的最大总价值。
在选择装入背包的物品时,对每件物品i ,要么装入背包,要么不装入背包。
不能将物品i 多次装入背包,也不能只装入部分物品i (分割物品i)。
因此,该问题称为0-1 背包问题。
用于求解0-1背包问题的方法主要有回溯算法、贪婪算法、遗传算法、禁忌搜索算法、模拟退火算法等。
在高中阶段,我们所谓的经典0-1背包问题,保证了所有量化后的数据均为正整数,即是一个特殊的整数规划问题,本文中如无特殊说明均以此为前提。
其经典的O(n*C)动规解法是:状态是在前i件物品中,选取若干件物品其体积总和不大于j,所能获得的最大价值为F i[j],当前的决策是第i件物品放或者不放,最终得到转移方程:F i[j] = F i-1[j] (V i>j>=0)F i[j] = max{ F i-1[j] , F i-1[j-V i]+W i } (C>=j>=V i)其中由于F i只与F i-1有关,可以用滚动数组来节省程序的空间复杂度。
C++动态规划求解0-1背包问题

C++动态规划求解0-1背包问题问题描述:给定n种物品和⼀背包。
物品i的重量是w i,其价值为v i,背包的容量为C。
问:应该如何选择装⼊背包的物品,是的装⼊背包中物品的总价值最⼤?细节须知:暂⽆。
算法原理:a.最优⼦结构性质0-1背包问题具有最优⼦结构性质。
设(y1,y2,…,y n)是所给0-1背包问题的⼀个最优解,则(y2,…,y n)是下⾯相应⼦问题的⼀个最优解。
b.递归关系设所给0-1背包问题的⼦问题的最优值为m(i,j),即m(i,j)是背包容量为j,可选择物品为i,i+1,…,n时0-1背包问题的最优值。
有0-1背包问题的最优⼦结构性质,可以建⽴如下计算m(i,j)的递归式1 #include <iostream>2 #include <fstream>3 #include <ctime>4 #include <algorithm>5 #include <windows.h>6using namespace std;7#define N 1000089//int w[5] = { 0 , 2 , 3 , 4 , 5 }; //商品的体积2、3、4、510//int v[5] = { 0 , 3 , 4 , 5 , 6 }; //商品的价值3、4、5、611//int bagV = 8; //背包⼤⼩12int dp[N][N]; //动态规划表13//int item[5]; //最优解情况1415void findMax(int k,int n,int w[],int v[]) { //动态规划16for (int i = 1; i <= k; i++) {17for (int j = 1; j <= n; j++) {18if (j < w[i])19 dp[i][j] = dp[i - 1][j];20else21 dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i]);22 }23 }24}2526void findWhat(int i, int j,int w[],int v[],int item[]) { //最优解情况27if (i > 0) {28if (dp[i][j] == dp[i - 1][j]) {29 item[i] = 0;30 findWhat(i - 1, j,w,v,item);31 }32else if (j - w[i] >= 0 && dp[i][j] == dp[i - 1][j - w[i]] + v[i]) {33 item[i] = 1;34 findWhat(i - 1, j - w[i],w,v,item);35 }36 }37}3839void print(int k,int n,int item[]) {40/*for (int i = 0; i < k+1; i++) { //动态规划表输出41 for (int j = 0; j < n+1; j++) {42 cout << dp[i][j] << ' ';43 }44 cout << endl;45 }46 cout << endl;*/47 cout <<"The item number that should be put into the backpack is:";48for (int i = 0; i < k+1; i++){ //最优解输出49if(item[i] == 1)50 cout << i << '';51 }52 cout << endl;53}5455int main(void)56{57 LARGE_INTEGER nFreq;58 LARGE_INTEGER nBeginTime;59 LARGE_INTEGER nEndTime;60 ofstream fout;61double cost;62int i,j,m,n,k;63 cout << "Please enter the number of times you want to run the program:";64 cin >> m;65//int object_amount[m];66//double runtime[m];67 fout.open("backpack.txt",ios::app);68if(!fout){69 cerr<<"Can not open file 'backpack.txt' "<<endl;70return -1;71 }72 fout.setf(ios_base::fixed,ios_base::floatfield); //防⽌输出的数字使⽤科学计数法73 srand((unsigned int)time(NULL));74for(i = 0; i < m; i++){75 n = rand()%10000;76 k = rand()%10000;77//object_amount[i] = k;78 fout<<k<<",";79int item[k];80 cout << "The " << i+1 << "th test's backpack lattice number is:" << n << endl;81 cout << "The " << i+1 << "th test's object amount is:" << k << endl;82int w[k];83int v[k];84 memset(dp,0,sizeof(dp));85 w[0] = 0;86 v[0] = 0;87for(j=1;j<k;j++){88 w[j]=rand()%100;89 v[j]=rand()%1000;90 }91 QueryPerformanceFrequency(&nFreq);92 QueryPerformanceCounter(&nBeginTime);93 findMax(k,n,w,v);94 findWhat(k,n,w,v,item);95 print(k,n,item);96 QueryPerformanceCounter(&nEndTime);97 cost=(double)(nEndTime.QuadPart - nBeginTime.QuadPart) / (double)nFreq.QuadPart; 98//runtime[i]=cost;99 fout<<cost<<endl;100 cout<<"The running time is:"<<cost<<" s"<<endl;101 }102/* fout.open("backpack.txt",ios::app);103 if(!fout){104 cerr<<"Can not open file 'backpack.txt' "<<endl;105 return -1;106 }107 fout.setf(ios_base::fixed,ios_base::floatfield); //防⽌输出的数字使⽤科学计数法108 for(i=0;i<m;i++){109 fout<<object_amount[i]<<","<<runtime[i]<<endl;110 }*/111 fout.close();112 cout<<"Success!"<<endl;113return0;114 }程序设计思路:根据算法原理中所述递归关系,递归计算全部的m(i,j),得到不同情况下的最优解。
ACM程序设计竞赛例题[1]
![ACM程序设计竞赛例题[1]](https://img.taocdn.com/s3/m/8e8360ed84868762cbaed565.png)
A C M程序设计竞赛例题[1]-CAL-FENGHAI.-(YICAI)-Company One1备战ACM资料习题1.0-1背包问题在0 / 1背包问题中,需对容量为c 的背包进行装载。
从n 个物品中选取装入背包的物品,每件物品i 的重量为wi ,价值为pi 。
对于可行的背包装载,背包中物品的总重量不能超过背包的容量,最佳装载是指所装入的物品价值最高。
程序如下:#include <>void readdata();void search(int);void checkmax();void printresult();int c=35, n=10; ");printf("\n");}printf("\n");}6.素数环问题把从1到20这20个数摆成一个环,要求相邻的两个数的和是一个素数。
分析:用回溯算法,考察所有可能的排列。
程序如下:#include <>#include <>void search(int);void init(); 表示空格;’X’表示墙。
程序如下:#include <>#include <>void search(int,int);int canplace(int,int);void readdata(); Floodfill给一个20×20的迷宫和一个起点坐标,用广度优先搜索填充所有的可到达的格子。
提示:参考第2题。
2. 电子老鼠闯迷宫如下图12×12方格图,找出一条自入口(2,9)到出口(11,8)的最短路本题给出完整的程序和一组测试数据。
状态:老鼠所在的行、列。
程序如下:#include<>void readdata();a[i][j]=0; ....注:测试数据可在运行时粘贴上去(点击窗口最左上角按钮,在菜单中选则“编辑”/“粘贴”即可)。
算法设计及实验报告

算法设计及实验报告实验报告1 递归算法一、实验目的掌握递归算法的基本思想;掌握该算法的时间复杂度分析;二、实验环境电脑一台,Turbo C 运行环境三、实验内容、步骤和结果分析以下是四个递归算法的应用例子:用C语言实现1.阶乘:main(){int i,k;scanf("%d\n",&i);k= factorial(i);printf("%d\n",k);}int factorial(int n){ int s;if(n==0) s=1;else s=n*factorial(n-1); //执行n-1次return s;}阶乘的递归式很快,是个线性时间,因此在最坏情况下时间复杂度为O(n)。
2.Fibonacci 数列:main(){int i,m;scanf("%d\n",&i);m=fb(i);printf("%d",m);}int fb(int n){int s;if(n<=1)return 1;else s=fb(n-1)+fb(n-2);return s;}Fibonacci数列则是T(n)=T(n-1)+T(n-2)+O(1)的操作,也就是T(n)=2T(n)+O(1),由递归方程式可以知道他的时间复杂度T(n)是O(2n),该数列的规律就是不停的赋值,使用的内存空间也随着函数调用栈的增长而增长。
3.二分查找(分治法)#include<stdio.h>#define const 8main(){int a[]={0,1,2,3,4,5,6,7,8,9};int n=sizeof(a);int s;s=BinSearch(a,const,n);printf("suo cha de shu shi di %d ge",s);}BinSearch(int a[],int x,int n){int left,right,middle=0;left=0;right=n-1;whlie(left<=right){middle=(left+right)/2;if(x==a[middle]) return middle;if(x>a[middle]) left=middle+1;else right=middle-1;}return -1;}二分搜索算法利用了元素间的次序关系,采用分治策略,由上程序可知,每执行一次while循环,数组大小减少一半,因此在最坏情况下,while循环被执行了O(logn)次。
05使用LINGO软件求解背包问题

05. 使用LINGO软件求解背包问题例1(0-1)背包问题为max x0=2x1+9x2+3x3+8x4+10x5+6x6+4x7+10x8s. t. x1+3x2+4x3+3x4+3x5+x6+5x7+10x8≤15x i=0, or 1使用Lingo软件求解,程序编制如下:!0-1背包问题(一维);model:sets:items/item1..item8/:include,weight,rating;endsetsdata:weight rating=1 23 94 33 83 101 65 410 10;knapsack_capacity=15;enddatamax=@sum(items:rating*include);@sum(items:weight*include)<=knapsack_capacity;@for(items:@bin(include));end使用Solve命令解得结果如下:Global optimal solution found.Objective value: 38.00000Extended solver steps: 0Total solver iterations: 0Variable Value Reduced Cost KNAPSACK_CAPACITY 15.00000 0.000000 INCLUDE( ITEM1) 1.000000 -2.000000INCLUDE( ITEM2) 1.000000 -9.000000INCLUDE( ITEM3) 1.000000 -3.000000INCLUDE( ITEM4) 1.000000 -8.000000INCLUDE( ITEM5) 1.000000 -10.00000INCLUDE( ITEM6) 1.000000 -6.000000INCLUDE( ITEM7) 0.000000 -4.000000INCLUDE( ITEM8) 0.000000 -10.00000WEIGHT( ITEM1) 1.000000 0.000000WEIGHT( ITEM2) 3.000000 0.000000WEIGHT( ITEM3) 4.000000 0.000000WEIGHT( ITEM4) 3.000000 0.000000WEIGHT( ITEM5) 3.000000 0.000000WEIGHT( ITEM6) 1.000000 0.000000WEIGHT( ITEM7) 5.000000 0.000000WEIGHT( ITEM8) 10.00000 0.000000RATING( ITEM1) 2.000000 0.000000RATING( ITEM2) 9.000000 0.000000RATING( ITEM3) 3.000000 0.000000RATING( ITEM4) 8.000000 0.000000RATING( ITEM5) 10.00000 0.000000RATING( ITEM6) 6.000000 0.000000RATING( ITEM7) 4.000000 0.000000RATING( ITEM8) 10.00000 0.000000Row Slack or Surplus Dual Price1 38.00000 1.0000002 0.000000 0.000000例2(二维背包问题) 某船的装载体积为1000m3,重量1200kg,现在需装9种货物,体积和重量如下表,求装哪些货物价值最大?货物 1 2 3 4 5 6 7 8 9 体积(m3) 774 76 22 42 21 760 818 62 782 重量(kg) 67 27 794 53 234 32 792 97 435 价值(千元) 77 6 3 6 33 13 110 21 47使用Lingo软件求解,程序编制如下:max=77*x1+6*x2+3*x3+6*x4+33*x5+13*x6+110*x7+21*x8+47*x9;774*x1+76*x2+22*x3+42*x4+21*x5+760*x6+818*x7+62*x8+782*x9<=1000;67*x1+27*x2+794*x3+53*x4+234*x5+32*x6+792*x7+97*x8+435*x9<=1200;@bin(x1);@bin(x2);@bin(x3);@bin(x4);@bin(x5);@bin(x6);@bin(x7);@bin(x8);@bin(x9);其中@bin(x)限制x为0或1。
《程序设计创新》分支限界法解决01背包问题

《程序设计创新》分支限界法解决01背包问题一、引言分枝限界法通常以广度优先或最小成本(最大收益)优先搜索问题的解空间树。
在分枝限界方法中,每个活动节点只有一次成为扩展节点的机会。
当活动节点成为扩展节点时,将同时生成所有子节点。
这些子节点将丢弃不可执行或非最优解的子节点,并将剩余的子节点添加到活动节点表中。
然后,从活动节点表中选择节点作为当前扩展节点,然后重复上述节点扩展过程。
此过程将持续到所需的解决方案或节点表为空。
二、研究背景在生活或企业活动中,我们常常会遇到一些装在问题。
例如在生活中我们要出去旅游,背包的容量是有限的而要装物品可能很多,但是每个物品的装载优先级肯定是不一样的,那么怎么装更合适一些呢。
在企业活动中,比如轮船集装箱装载问题,集装箱是有限的,那么怎么装载这些货物才能每次都是装载最多的,只有这样企业利润才能最大化。
三、相关技术介绍上述问题就是我们算法中会遇到的背包问题。
而背包问题又分许多。
如背包问题,通常用贪心法解决。
如01背包问题通常用动态规划或者分支限界法解决。
本次我们考虑使用分支限界法来解决01背包问题四、应用示例在01背包问题中,假设有四个物品。
重量W(4,7,5,3),价值V(40,42,25,12),背包重量W为10,试求出最佳装载方案。
定义限界函数: ub = v + (W-w)×(Vi+1/W+1)画出状态空间树的搜索图步骤:①在根结点1,没有将任何物品装入背包,因此,背包的重量和获得的价值均为0,根据限界函数计算结点1的目标函数值为10×10=100;②在结点2,将物品1装入背包,因此,背包的重量为4,获得的价值为40,目标函数值为40 + (10-4)×6=76,将结点2加入待处理结点表PT中;在结点3,没有将物品1装入背包,因此,背包的重量和获得的价值仍为0,目标函数值为10×6=60,将结点3加入表PT 中;③在表PT中选取目标函数值取得极大的结点2优先进行搜索;④在结点4,将物品2装入背包,因此,背包的重量为11,不满足约束条件,将结点4丢弃;在结点5,没有将物品2装入背包,因此,背包的重量和获得的价值与结点2相同,目标函数值为40 + (10-4)×5=70,将结点5加入表PT中;⑤在表PT中选取目标函数值取得极大的结点5优先进行搜索;⑥在结点6,将物品3装入背包,因此,背包的重量为9,获得的价值为65,目标函数值为65 + (10-9)×4=69,将结点6加入表PT中;在结点7,没有将物品3装入背包,因此,背包的重量和获得的价值与结点5相同,目标函数值为40 + (10-4)×4=64,将结点6加入表PT中;⑦在表PT中选取目标函数值取得极大的结点6优先进行搜索;⑧在结点8,将物品4装入背包,因此,背包的重量为12,不满足约束条件,将结点8丢弃;在结点9,没有将物品4装入背包,因此,背包的重量和获得的价值与结点6相同,目标函数值为65;⑨由于结点9是叶子结点,同时结点9的目标函数值是表PT中的极大值,所以,结点9对应的解即是问题的最优解,搜索结束。
智慧树知到《算法分析与设计》章节测试答案

智慧树知到《算法分析与设计》章节测试答案第一章1、给定一个实例,如果一个算法能得到正确解答,称这个算法解答了该问题。
A:对B:错答案: 错2、一个问题的同一实例可以有不同的表示形式A:对B:错答案: 对3、同一数学模型使用不同的数据结构会有不同的算法,有效性有很大差别。
A:对B:错答案: 对4、问题的两个要素是输入和实例。
A:对B:错答案: 错5、算法与程序的区别是()A:输入B:输出C:确定性D:有穷性答案: 有穷性6、解决问题的基本步骤是()。
(1)算法设计(2)算法实现(3)数学建模(4)算法分析(5)正确性证明A:(3)(1)(4)(5)(2)B:(3)(4)(1)(5)(2)C:(3)(1)(5)(4)(2)D:(1)(2)(3)(4)(5)答案: (3)(1)(5)(4)(2)7、下面说法关于算法与问题的说法错误的是()。
A:如果一个算法能应用于问题的任意实例,并保证得到正确解答,称这个算法解答了该问题。
B:算法是一种计算方法,对问题的每个实例计算都能得到正确答案。
C:同一问题可能有几种不同的算法,解题思路和解题速度也会显著不同。
D:证明算法不正确,需要证明对任意实例算法都不能正确处理。
答案: 证明算法不正确,需要证明对任意实例算法都不能正确处理。
8、下面关于程序和算法的说法正确的是()。
A:算法的每一步骤必须要有确切的含义,必须是清楚的、无二义的。
B:程序是算法用某种程序设计语言的具体实现。
C:程序总是在有穷步的运算后终止。
D:算法是一个过程,计算机每次求解是针对问题的一个实例求解。
答案: 算法的每一步骤必须要有确切的含义,必须是清楚的、无二义的。
,程序是算法用某种程序设计语言的具体实现。
,算法是一个过程,计算机每次求解是针对问题的一个实例求解。
9、最大独立集问题和()问题等价。
A: 最大团B:最小顶点覆盖C:区间调度问题D:稳定匹配问题答案:最大团,最小顶点覆盖10、给定两张喜欢列表,稳定匹配问题的输出是()。
01背包问题分支限界法在C++程序实现中的难点解析

形的观测数据报告显示,路基填筑后沉降以及路基稳定沉降 量都在控制的设计范围之内。
三、结语 广珠铁路丹灶站场建设当中,通过对软基处理新工艺的 研究,实施工程保 证 措 施,最 终 达 到 圆 满 完 成 工 程 任 务 的 目 的。广珠公司及铁四院业内专家认为,新型外加剂的钉形水 泥土双向搅拌桩 + 塑料排水板工艺对于工程质量保证及工 期保障起到 了 关 键 性 作 用,广 珠 公 司 及 铁 四 院 业 内 专 家 认 为,本技术在推广和应用潜力将是巨大的。
【关键词】计算方法; 限界函数; 剪枝处理 【作者简介】赵鑫,男,黑河学院计算机科学与信息工程系 2008 级网络工程专业学生; 研究方向: 数据库检索算法
一、引言 在学习《算法设计与分析》课程的 0 /1 背包问题分支限 界法 C + + 实现时,同学们对算法中的限界函数和剪枝处理 理解起来很困难,为 此 专 门 撰 写 这 篇 文 章 和 大 家 一 起 学 习、 探讨和解决这两个难点。 二、限界函数的实现算法分析 0 /1 背包问题分支限界法 C + + 实现程序中限界函数的 具体实现源代码如下: void LcKnap: : LUBound( int rw,int cp,int k,int &LB,float &UB) { / / 计算结点目标函数的上下限值,重量数组和价值数
Industrial & Science Tribune 211 卷第 3 期
{ if( c > = w[j]) / / 第 i + 1( 下一个) 个物品可以放入背包 { c = c - w[j]; LB + = p[j]; / / 用贪心法的一个解作为下限 } } return; } c = c - w[i]; / / 背包能装下物品 i,即 c > w[i] LB + = p[i]; } UB = ( float) LB; / / 物品全部装入时,有 LB = UB return; } 这个程序总体功能是计算 0 /1 背包问题上下限函数的 值,具体实现算法是用贪心法求解上限值 UB 和下限值 LB。 其中求上限值 UB 是利用背包问题的贪心算法实现的,而求 下限值 LB 是利用 0 /1 背包问题的贪心算法实现的。这样, 两种不同问题的算法偏偏溶于一个 0 /1 背包问题分支限界 法中,造成了理 解 求 限 界 函 数 的 困 难 。 我 们 应 该 首 先 学 习 和区分 0 /1 背包问题和背包问题概念和算法的细微差别, 然后阅读和学习这里讲的 0 /1 背包问题的分支限界法就可 以了。 三、对剪枝处理的深入解析 void LcKnap: : LCKNAP( ) { / /求解背包问题 …… while( E - > ub > L) / / 当前扩展结点目标函数值 > 当前 可行解 { …… if( i = = N) / / 解结点,处理第 n 个物品 { if( prof > L) { L = ( float) prof; / / 用叶子结点的值修正解 L 的值 ANS = E; / / 用回溯法求出解的具体分支是 0 或 1 } } else / / E 有两个子结点 { if( cap > = w[i]) / / 左子结点可行,当前物品可以放入 背包 { EnQueue( NewNode( E,i + 1,1,cap - w[i],prof + p[i],E - > ub,E - > lb) ) ; / / 左子结点加入优先队列 } LUBound( cap,prof,i + 1,lb,ub) ; / / 重新计算上下界 if( ubb > L) / / 右子结点可行,即当前物品不能放入背包
01背包问题程序解析

01背包问题程序解析#include <iostream>#include <cstdio>#include <cstring>using namespace std;//问题描述:给定 n 种物品和⼀个容量为 c 的背包,物品 i 的重量是 wi,其价值为 vi.//问:应该如何选择装⼊背包的物品,使得装⼊背包中的物品的总价值最⼤?//分析:⾯对每个物品,我们只有选择拿取或者不拿两种选择,不能选择装⼊某物品的⼀部分,也不能装⼊同⼀物品多次//解决⽅法:声明⼀个⼤⼩为 m[n][c] 的⼆维数组,m[i][j] 表⽰在⾯对第 i 件物品,且背包容量为 j 时所能获得的最⼤价值,那么我们可以很容易分析得出 m[i][j] 的计算⽅法,/*(1).j < w[i]的情况,这时候背包容量不⾜以放下第 i 件物品,只能选择不拿m[i][j] = m[i-1][j](2).j >= w[i]的情况,这时背包容量可以放下第 i 件物品,我们就要考虑拿这件物品是否能获得更⼤的价值.如果拿取,m[i][j] = m[i-1][j - w[i]] + v[i].这⾥的m[i - 1][j - w[i]]指的是考虑了i-1件物品,背包容量为j - w[i] 时的最⼤价值,也是相当于为第i件物品腾出了w[i]的空间.如果不拿,m[i][j] = m[i -1][j],同(1)究竟是拿还是不拿,⾃然是⽐较这两种情况哪种价值最⼤.由此可以得到状态转移⽅程:if(j >= w[i])m[i][j] = max(m[i-1][j],m[i-1][j-w[i]] + v[i]);elsem[i][j] = m[i-1][j];例⼦:价值数组v = {8, 10, 6, 3, 7, 2},重量数组w = {4, 6, 2, 2, 5, 1},背包容量C = 12时对应的m[i][j]数组。
0-1背包问题蛮力法求解(c++版本)

0-1背包问题蛮⼒法求解(c++版本)// 0.1背包求解.cpp : 定义控制台应⽤程序的⼊⼝点。
//#include "stdafx.h"#include <iostream>#define N 5#define ST 10using namespace std;int main() {//给定n个重量,价值为不同的个物品和容量为c的背包,求这些物品中⼀个最有的价值的⼦集int a[N] = { 2, 1, 3, 4, 7 };int b[N] = { 2, 5, 4, 1, 2 };int sum1 = 0;//sum1表⽰最终的价值for (int i = 0; i<N; i++)//这是对每次的{int STS = 0;//⾦⼦的总个数int QS = 0;//价值的总个数for (int j = 0; j<N; j++){if (STS + a[i]<ST)//如果⾦⼦每放完,则继续放{cout << "⾦⼦个数:" << a[j] << " ";cout << "对应的价值为:" << a[j] * b[j] << endl;STS += a[j];QS += a[j] * b[j];}//否则则不进⾏}//直到这个循环结束后就出来求出总的价值cout << "第" << i + 1 << "次的总价值为:" << QS << endl;cout << endl;if (QS>sum1){sum1 = QS;}}cout << "蛮⼒法背包最⼤的价值为:" << sum1 << endl;return 0;}结语> 如果你还需要了解更多技术⽂章信息,请继续关注的博客。
优先队列式分支限界法求解0-1背包问题

算法分析与设计实验报告第7 次实验}1、测试自己输入的小规模数据2、测试随机生成1003、随机生成1000数据4、随机生成1000数据附录:完整代码#include <iostream>#include<time.h>#include<algorithm>#include<fstream>using namespace std;ifstream in("input.txt");ofstream out("output.txt");typedef int Typew;typedef int Typep;//物品类class Object{friend Typep Knapsack(Typew *, Typep *, Typew, int, int *); public:int operator <= (Object a) const{return (d >= a.d);}private:int ID; //物品编号float d; //单位重量价值};//树结点类class bbnode{friend class Knap;friend Typep Knapsack(Typew *, Typep *, Typew, int, int *); private:bbnode *parent; //指向父节点的指针int LChild;};//堆结点类class HeapNode{friend class Knap;friend class MaxHeap;public:operator Typep()const{return uprofit;};private:Typep uprofit, //结点的价值上界profit; //结点所相应的价值Typew weight; //结点所相应的重量int level; //活结点在子集树中所处的层序号bbnode *elemPtr; //指向该活结点在子集树中相应结点的指针};//最大堆类class MaxHeap{public:MaxHeap(int maxElem){HeapElem = new HeapNode* [maxElem+1]; //下标为0的保留capacity = maxElem;size = 0;}void InsertMax(HeapNode *newNode);HeapNode DeleteMax(HeapNode* &N);private:int capacity;int size;HeapNode **HeapElem;};//0-1背包问题的主类class Knap{friend Typep Knapsack(Typew *, Typep *, Typew, int, int *); public:Typep MaxKnapsack();private:MaxHeap *H;Typep Bound(int i);void AddLiveNode(Typep up, Typep cp, Typew cw, int ch, int level);bbnode *E; //指向扩展结点的指针Typew c; //背包容量int n; //物品总数Typew *w; //物品重量数组(以单位重量价值降序)Typep *p; //物品价值数组(以单位重量价值降序)Typew cw; //当前装包重量Typep cp; //当前装包价值int *bestx; //最优解};void MaxHeap::InsertMax(HeapNode *newNode){int i = 1;for (i = ++size; i/2 > 0 && HeapElem[i/2]->uprofit < newNode->uprofit; i /= 2){HeapElem[i] = HeapElem[i/2];}HeapElem[i] = newNode;}HeapNode MaxHeap::DeleteMax(HeapNode *&N){if(size >0 ){N = HeapElem[1];int i = 1;while(i < size){if(((i*2 +1) <= size) && HeapElem[i*2]->uprofit > HeapElem[i*2 +1]->uprofit){HeapElem[i] = HeapElem[i*2];i = i*2;}else{if(i*2 <= size){HeapElem[i] = HeapElem[i*2];i = i*2;}elsebreak;}}if(i < size)HeapElem[i] = HeapElem[size];}size--;return *N;}Typep Knap::MaxKnapsack(){H = new MaxHeap(10000);bestx = new int [n+1];int i = 1;E = 0;cw = 0;cp = 0;Typep bestp = 0;Typep up = Bound(1);while (i != n+1){Typew wt = cw + w[i];if(wt <= c) {if(cp + p[i] > bestp)bestp = cp + p[i];AddLiveNode(up, cp + p[i], cw + w[i], 1, i);}up = Bound(i + 1);if(up >= bestp)AddLiveNode(up, cp, cw, 0, i);HeapNode* N;H->DeleteMax(N);E = N->elemPtr;cw = N->weight;cp = N->profit;up = N->uprofit;i = N->level + 1;}for (int i = n; i > 0; i--){bestx[i] = E->LChild;E = E->parent;}return cp;}Typep Knap::Bound(int i){Typew cleft = c - cw;Typep b = cp;while (i<=n && w[i] <= cleft){cleft -= w[i];b += p[i];i++;}if(i<=n) b += p[i]/w[i] * cleft;return b;}void Knap::AddLiveNode(Typep up, Typep cp, Typew cw, int ch, int level) {bbnode *b=new bbnode;b->parent=E;b->LChild=ch;HeapNode *N = new HeapNode;N->uprofit=up;N->profit=cp;N->weight=cw;N->level=level;N->elemPtr=b;H->InsertMax(N);}//Knapsack返回最大价值,最优值保存在bestxTypep Knapsack(Typew *w, Typep *p, Typew c, int n, int *bestx){Typew W = 0;Typep P = 0;Object *Q = new Object[n];for(int i =1; i<=n; i++){Q[i-1].ID = i;Q[i-1].d = 1.0*p[i]/w[i];P += p[i];W += w[i];}if (W <= c){for(int i =1; i<=n; i++){bestx[i] = p[i];}return P;}for(int i = 1; i<n; i++)for(int j = 1; j<= n-i; j++){if(Q[j-1].d < Q[j].d){Object temp = Q[j-1];Q[j-1] = Q[j];Q[j] = temp;}}Knap K;K.p = new Typep [n+1];K.w = new Typew [n+1];for(int i = 1; i<=n; i++){K.p[i] = p[Q[i-1].ID];K.w[i] = w[Q[i-1].ID];}K.cp = 0;K.cw = 0;K.c = c;K.n = n;Typep bestp = K.MaxKnapsack();for(int i = 1; i<=n; i++){bestx[Q[i-1].ID] = K.bestx[i];}delete [] Q;delete [] K.w;delete [] K.p;delete [] K.bestx;delete [] K.H;return bestp;}int main(){cout<<"请在input.txt文件中输入物品数量、背包容量"<<endl;int N ;in>>N;Typew c; //背包容量in>>c;int bestx[N+1]; //最优解int bestp; //最优值Typep p[N+1];//物品价值Typew w[N+1];//物品重量cout<<"在input.txt文件中读取的物品总数N = "<< N<<",背包容量C = "<< c<<endl; cout<<"请选择生成数据的规模大小:200请输入1,2000请输入2,20000请输入3"<<endl; int x;cin>>x;if(x==1){ofstream in1("input1.txt");srand(time(NULL));int n=200;int *a=new int[n];for(int i=0;i<n;i++){a[i]=rand()%91;in1<<a[i]<<" ";}cout<<"随机数已请生成到input1文件中,请将数据添加到input.txt文件中"<<endl; }else if(x==2){ofstream in1("input1.txt");srand(time(NULL));int n=2000;int *a=new int[n];for(int i=0;i<n;i++){a[i]=rand()%91;in1<<a[i]<<" ";}cout<<"随机数已请生成到input1文件中,请将数据添加到input.txt文件中"<<endl; }else if(x==3){ofstream in1("input1.txt");srand(time(NULL));int n=20000;int *a=new int[n];for(int i=0;i<n;i++){a[i]=rand()%91;in1<<a[i]<<" ";}cout<<"随机数已请生成到input1文件中,请将数据添加到input.txt文件中"<<endl;}cout<<"添加完毕后请输入1"<<endl;int m;cin>>m;clock_t start,finish;start=clock();for (int i = 1; i <= N; i++){in>>w[i];}for (int i = 1; i <= N; i++){in>>p[i];}cout<<"已在input文件中读取物品重量和价值。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
问题描述:
01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的体积为W1,W2……Wn,与之相对应的价值为P1,P2……Pn。
求出获得最大价值的方案。
在本例中所有数值均为整数
代码实现:
// Knapsack.h
#ifndef KNAPSACK_H
#define KNAPSACK_H
class Knapsack
{
public:
Knapsack();
~Knapsack();
void run(); // 运行接口
private:
int number; // 记录物品数量
int MaxCapacity; // 最大容量
int MaxValue; // 记录计算到的最大价值量
int *v; // 物品价值
int *x; // 记录物品的取舍
int **m; // 纪录最大价值量
bool input(); // 输入接口
int lagestValue(int *W,int *V,int n,int m); // 计算最大价值void output(); // 输出接口显示
void traceback();
};
#endif
// Knapsack.cpp
#include <iostream>
#include <iostream.h>
#include <fstream>
#include <fstream.h>
#include <cstdlib>
#include <iomanip>
#include "Knapsack.h"
#define N 50 // 定义物品数量为50
ifstream inputFile("intput.txt",ios::in);
ofstream outputFile("output.txt",ios::out);
Knapsack::Knapsack()
{
number=0;
MaxValue=0;
MaxCapacity=0;
w=new int [N];
v=new int [N];
x=new int [N];
m=new int *[N];
for (int i=0;i<N;i++)
{
m[i]=new int [N]; // 要确保大于 MaxCapacity
Knapsack::~Knapsack()
{
delete []w;
delete []v;
delete []x;
for (int i=0;i<N;i++)
{
delete []m[i];
}
delete []m;
}
void Knapsack::run() // 运行接口
{
if (input())
{
MaxValue=lagestValue(w,v,1,MaxCapacity);
output();
}
bool Knapsack::input()
{
inputFile>>number; // 读取物品的数量个数
outputFile<<number<<" ";
inputFile>>MaxCapacity; // 读取背包的容量
outputFile<<MaxCapacity<<endl<<endl;;
for (int i=1;i<=number;i++) // 物品计数从1开始{
inputFile>>w[i];
outputFile<<w[i]<<" ";
}
outputFile<<endl<<endl;
for (i=1;i<=number;i++)
{
inputFile>>v[i];
outputFile<<v[i]<<" ";
}
outputFile<<endl<<endl;
if (w!=NULL && v!=NULL)
{
return true;
}
return false;
}
int Knapsack::lagestValue(int *W,int *V,int i,int j) // n 为物品 m 为容量
{
if (i<number)
{
if (j>=w[i])
{
int T1=lagestValue(w,v,i+1,j);
int T2=lagestValue(w,v,i+1,j-w[i])+v[i];
m[i][j]=( T1 > T2 ? T1 : T2);
return m[i][j];
}
else if (j>=0 && j<w[i])
{
return m[i][j];
}
}
else if(i==number)
{
if (j>=w[i])
{
m[i][j]=v[number];
return m[i][j];
}
else
{
m[i][j]=0;
return 0;
}
}
return 0;
}
void Knapsack::output() {
outputFile<<"放入背包的物品分别为:"<<endl<<endl;;
traceback();
}
void Knapsack::traceback()
{
int j=MaxCapacity;
for (int i=1;i<number;i++)
{
if (m[i][j]==m[i+1][j])
{
x[i]=0;
}
else
{
x[i]=1;
j-=w[i];
}
}
int count=0; // 记录放入背包的物品的总重量
for (i=1;i<=number;i++)
{
if (x[i]==1)
{
outputFile<<"物品"<<i<<" "<<"重量为:"<<w[i]<<" "<<"价值量为:"<<v[i]<<endl;
count+=w[i];
}
}
outputFile<<endl;
outputFile<<"背包的最大容量是: "<<MaxCapacity<<" 放入背包的物品的总重量是:"<<count<<endl;
}
// main.cpp
#include "Knapsack.h"
int main()
Knapsack k;
k.run();
return 0; }。