0-1背包问题

 给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。
   问应如何选择装入背包的物品,使得装入背包中物品的总价值最大
  对于一种物品,要么装入背包,要么不装。所以对于一种物品的装入状态可以取0和1.
  我们设物品i的装入状态为xi,xi∈ (0,1),此问题称为0-11背包问题。
  过程分析
  数据:物品个数n=5,物品重量w[n]={2,2,6,5,4},物品价值V[n]={6,3,5,4,6},
总重量c=10.背包的最大容量为10,那么在设置数组m大小时,可以设行列值为6和11,

那么,对于m(i,j)就表示可选物品为i…n背包容量为j(总重量)时背包中所放物品的最大价值。

动态规划

#include<stdio.h>
#define n 5
#define c 10
	//int j;
	int w[n]={2,2,6,5,4};
	int v[n]={6,3,5,4,6};
	int s[n][c+1];
	int knap(){
	  for(int j=0;j<=c;j++){//j表背包容量 
		if(j<w[n-1])
			s[n-1][j]=0;   
	    else s[n-1][j]=v[n-1];//当j>=w[n-1]时,表背包可以放入物体n-1,故其价值为v[n] 
	 }
	  for(int i=n-2;i>=0;i--){
  		for(int j=0;j<=c;j++){
	      if(j<w[i])
	        s[i][j]=s[i+1][j];
          else s[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]);
	     }			     
  	}
  	int t=c;
    for(int i=0;i<n-1;i++)
       if(s[i][t]!=s[i+1][t]){
             	printf("%5d",i);
             	t=t-w[i];//如果放进去了,背包的容量就会相应减少 
             }
            if(t>=w[n-1])
			   printf("%5d",n-1); 
}
int main(){
   
   	 printf("0-1背包最优解为:");
	 knap(); 
	 printf("\n");   
     printf("s数组元素为:\n");
  	 for(int i=0;i<n;i++){
	  	for(int j=0;j<=c;j++){
	  		printf("%5d",s[i][j]);
	  	}
  	    printf("\n");
	  }	
	 printf("0-1最优值为:%d\n",s[0][c]);
	 return 0; 
} 

回溯法

#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 s[n][c+1];
int max=0;
int countv=0;
int countw=0;
int x[n];
int bestx[n];
void trace(int t){
	if(t==n){
		if(countw<=c){
			if(countv>max){
				max=countv;
				for(int i=0;i<n;i++)
					bestx[i]=x[i]; 
			}
			 
		}
		return;
	}
	countv+=v[t];
	countw+=w[t];
	x[t]=1;
	if(countw<=c)
	trace(t+1);
	countw-=w[t];
	countv-=v[t];
	x[t]=0;
	trace(t+1);
	
} 

int main(){
	trace(0);
	printf("%d",max);
	for(int i=0;i<n;i++)
		if(bestx[i]==1)
		printf("%5d",i);
	return 0;
} 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值