0/1背包问题1. 问题描述给定一个载重量为m,n个物品,其重量为w i,价值为v i,1<=i<=n,要求:把物品装入背包,并使包内物品价值最大2. 问题分析在0/1背包问题中,物体或者被装入背包,或者不被装入背包,只有两种选择。
循环变量i,j意义:前i个物品能够装入载重量为j的背包中(n+1)*(m+1)数组value意义:value[i][j]表示前i个物品能装入载重量为j的背包中物品的最大价值若w[i]>j,第i个物品不装入背包否则,若w[i]<=j且第i个物品装入背包后的价值>value[i-1][j],则记录当前最大价值(替换为第i个物品装入背包后的价值)计算最大价值的动态规划算法如下://计算for(i=1;i<row;i++){for(j=1;j<col;j++){//w[i]>j,第i个物品不装入背包value[i][j]=value[i-1][j];//w[i]<=j,且第i个物品装入背包后的价值>value[i-1][j],则记录当前最大价值int temp=value[i-1][j-w[i]]+v[i];if(w[i]<=j && temp>value[i][j])value[i][j]=temp;}}即该段程序完成以下n个阶段:1:只装入1个物品,确定在各种不同载重量的背包下,能够得到的最大价值2:装入2个物品,确定在各种不同载重量的背包下,能够得到的最大价值。
n:以此类推,装入n个物品,确定在各种不同载重量的背包下,能够得到的最大价值3. 问题求解确定装入背包的具体物品,从value[n][m]向前逆推:若value[n][m]>value[n-1][m],则第n个物品被装入背包,且前n-1个物品被装入载重量为m-w[n]的背包中否则,第n个物品没有装入背包,且前n-1个物品被装入载重量为m的背包中以此类推,直到确定第一个物品是否被装入背包为止。
逆推代码如下://逆推求装入的物品j=m;for(i=row-1;i>0;i--){if(value[i][j]>value[i-1][j]){c[i]=1;j-=w[i];}}4. 代码如下输入数据及输出数据均在文件中。
输入数据格式:n mw1 w2 ... w nv1 v2 ... vn输出数据格式:maxValuei count //i表示物品编号,count表示该物品被选中次数 .../************************************************************************* 0/1背包问题求解 (visual studio 2005)* 给定一个载重量为m,及n个物品,其重量为wi,价值为vi,1<=i<=n* 要求:把物品装入背包,并使包内物品价值最大************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#define FILENAMELENGTH 100class CBeibao{public:int m_nNumber; //物品数量int m_nMaxWeight; //最大载重量int *m_pWeight; //每个物品的重量int *m_pValue; //每个物品的价值int *m_pCount; //每个物品被选中的次数int m_nMaxValue; //最大价值public:CBeibao(const char *filename);~CBeibao();int GetMaxValue();int GetMaxValue(int n,int m,int *w,int *v,int *c);void Display(int nMaxValue);void Display(int nMaxValue,const char *filename); };//读入数据CBeibao::CBeibao(const char *filename){FILE *fp=fopen(filename,"r");if(fp==NULL){printf("can not open file!");return; //exit(0);}//读入物品数量和最大载重量fscanf(fp,"%d%d",&m_nNumber,&m_nMaxWeight);m_pWeight=new int[m_nNumber+1];m_pValue=new int[m_nNumber+1];m_pWeight[0]=0;//读入每个物品的重量for(int i=1;i<=m_nNumber;i++)fscanf(fp,"%d",m_pWeight+i);m_pValue[0]=0;//读入每个物品的价值for(int i=1;i<=m_nNumber;i++)fscanf(fp,"%d",m_pValue+i);//初始化每个物品被选中次数为0m_pCount=new int[m_nNumber+1];for(int i=0;i<=m_nNumber;i++)m_pCount[i]=0;fclose(fp);}CBeibao::~CBeibao(){delete[] m_pWeight;m_pWeight=NULL;delete[] m_pValue;m_pValue=NULL;delete[] m_pCount;m_pCount=NULL;}/************************************************************************* 动态规划求出满足最大载重量的最大价值* 参数说明:n:物品个数* m:背包载重量* w:重量数组* v:价值数组* c:是否被选中数组* 返回值:最大价值************************************************************************/int CBeibao::GetMaxValue(int n,int m,int *w,int *v,int *c){int row=n+1;int col=m+1;int i,j; //循环变量:前i个物品能够装入载重量为j的背包中//value[i][j]表示前i个物品能装入载重量为j的背包中物品的最大价值int **value=new int*[row];for(i=0;i<row;i++)value[i]=new int[col];//初始化第0行for(j=0;j<col;j++)value[0][j]=0;//初始化第0列for(i=0;i<row;i++)value[i][0]=0;//计算for(i=1;i<row;i++){for(j=1;j<col;j++){//w[i]>j,第i个物品不装入背包value[i][j]=value[i-1][j];//w[i]<=j,且第i个物品装入背包后的价值>value[i-1][j],则记录当前最大价值int temp=value[i-1][j-w[i]]+v[i];if(w[i]<=j && temp>value[i][j])value[i][j]=temp;}}//逆推求装入的物品j=m;for(i=row-1;i>0;i--){if(value[i][j]>value[i-1][j]){c[i]=1;j-=w[i];}}//记录最大价值int nMaxVlaue=value[row-1][col-1];//释放该二维数组for(i=0;i<row;i++){delete [col]value[i];value[i]=NULL;}delete[] value;value=NULL;return nMaxVlaue;}int CBeibao::GetMaxValue(){int nValue=GetMaxValue(m_nNumber,m_nMaxWeight,m_pWeight,m_pValue,m_pC ount);m_nMaxValue=nValue;return nValue;}//显示结果void CBeibao::Display(int nMaxValue){printf(" %d ",nMaxValue);for(int i=1;i<=m_nNumber;i++){if(m_pCount[i])printf(" %d %d ",i,m_pCount[i]);}printf(" ");}void CBeibao::Display(int nMaxValue,const char *filename){FILE *fp=fopen(filename,"w");if(fp==NULL){printf("can not write file!");return; //exit(0);}fprintf(fp,"%d ",nMaxValue);for(int i=1;i<=m_nNumber;i++){if(m_pCount[i])fprintf(fp,"%d %d ",i,m_pCount[i]);}fclose(fp);}//显示菜单void show_menu(){printf("--------------------------------------------- ");printf("input command to test the program ");printf(" i or I : input filename to test ");printf(" q or Q : quit ");printf("--------------------------------------------- ");printf("$ input command >");}void main(){char sinput[10];char sfilename[FILENAMELENGTH];show_menu();scanf("%s",sinput);while(stricmp(sinput,"q")!=0){if(stricmp(sinput,"i")==0){printf(" please input a filename:");scanf("%s",sfilename);//获取满足最大载重量的最大价值CBeibao beibao(sfilename);int nMaxValue=beibao.GetMaxValue();if(nMaxValue){beibao.Display(nMaxValue);int nlen=strlen(sfilename);strcpy(sfilename+nlen-4,"_result.txt");beibao.Display(nMaxValue,sfilename);}elseprintf(" error! please check the input data! ");}//输入命令printf("$ input command >");scanf("%s",sinput);}}5. 运行结果如下文件中的内容如下:1. input.txt4 102 3 4 71 3 5 9input_result.txt122 14 12. input1.txt5 102 2 6 5 46 3 5 4 6input1_result.txt151 12 15 13. input2.txt5 152 6 4 7 91 6 5 9 4input2_result.txt161 12 14 14. input3.txt10 10512 16 24 7 29 32 5 43 31 111 16 15 9 24 25 3 32 41 7input3_result.txt1121 12 14 16 17 19 110 1。