0-1背包问题

来源:互联网 发布:skype business mac 编辑:程序博客网 时间:2024/06/08 12:10

问题:给定一个容积为c的背包,去尝试装n个重量为wi、价值为vi的物体,求能装下的物体的最大价值。

 

解法一:暴力

分析:0-1背包只有两种选择,放与不放到背包里,采用二进制表示,1表示放入背包,0表示不放入背包,因此我们基于二进制进行暴力搜索。

#include<stdio.h>#include<math.h>#define n 5int weight[n]={12,2,1,4,1};int value[n]={4,2,1,10,2};int c=15;int main(){int maxvalue=0;int tempvalue,tempweight,temp,maxnum;for(int num=0;num<pow(2,n);num++){temp=num;tempvalue=0;tempweight=0;for(int i=0;i<n;i++){if(temp%2){tempvalue+=value[i];tempweight+=weight[i];}temp/=2;}if(tempweight<=c&&tempvalue>maxvalue){maxvalue=tempvalue;maxnum=num; }}for(int i=0;i<n;i++){if(maxnum%2)printf("%2d",weight[i]);maxnum/=2;}printf("\n该重量最大价值%d\n",maxvalue);return 0;} 

解法二:递归

分析:若飞f(i,j)表示考虑第i个物品时背包剩余容积为j

    j>=w[i]f(n,j)=v[i];

(1)i==n时:

当j<w[i]f(n,j)=0;当j>=w[i],f(i,j)=v[i];

(2)i<n时:

当j<w[i], f(i,j)=f(i+1,j);当j>=w[i], f(i,j)=max(f(i+1,j),f(i+1,j-w[i])+v[i]);


#include<stdio.h>#include<math.h>#define n 5#define c 10//递归实现 int w[n]={2,2,6,5,4};int v[n]={6,3,5,4,6};int f(int i,int j){//第i个物体,剩余容积 int m1,m2;if(i==n-1){if(j>=w[i])return v[i];return 0;}if(j<w[i]){return f(i+1,j);}m1=f(i+1,j);m2=f(i+1,j-w[i])+v[i];return m1>m2?m1:m2;}int main(){printf("%d\n",f(0,c));return 0;} 
解法三:动态规划

#include<stdio.h>#include<math.h>#define n 5#define c 10int w[n]={2,2,6,5,4};int v[n]={6,3,5,4,6};
int main(){int s[n][c+1];int i,j;for(j=0;j<c+1;j++){if(j>=w[n-1]){s[n-1][j]=v[n-1];}else{s[n-1][j]=0;}}for(i=n-2;i>=0;i--){for(j=0;j<c+1;j++){if(j<w[i])s[i][j]=s[i+1][j];elses[i][j]=s[i+1][j]>(s[i+1][j-w[i]]+v[i])?s[i+1][j]:(s[i+1][j-w[i]]+v[i]);}}printf("%4d\n",s[0][c]);j=c;for(i=0;i<n-1;i++){if(s[i][j]!=s[i+1][j]){printf("%4d",i+1);j-=w[i];}}if(j>=w[n-1]){printf("%4d",n);j-=w[i];}return 0;}

解法四:备忘录


int s[n][c+1];int f(int i,int j){int m1,m2;if(s[i][j]==0)return s[i][j];if(i==n-1){if(j>=w[i])s[i][j]=v[i];elses[i][j]=0;}else{if(j<w[i])s[i][j]=f(i+1,j);else{m1=f(i+1,j);m2=f(i+1,j-w[i])+v[i];s[i][j]=m1>m2?m1:m2;}}return s[i][j];}int main(){int i,j;for(i=0;i<n;i++){for(j=0;j<c+1;j++){s[i][j]=-1;}}printf("%4d\n",f(0,c));j=c;for(i=0;i<n-1;i++){if(s[i][j]!=s[i+1][j]){printf("%4d",i+1);j-=w[i];}}if(j>=w[n-1]){printf("%4d",n);j-=w[i];}return 0;}



原创粉丝点击