南邮 OJ 1308 背包问题

背包问题

时间限制(普通/Java) :  1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 82            测试通过 : 31 

比赛描述

         试设计一个用回溯法搜索子集空间树的函数。该函数的参数包括结点可行性判定函数和上界函数等必要的函数,并将此函数用于解0-1背包问题。

0-1 背包问题描述如下:给定n 种物品和一个背包。物品i 的重量是 wi ,其价值为 v i,背包的容量为C。应如何选择装入背包的物品,使得装入背包中物品的总价值最大?

在选择装入背包的物品时,对每种物品i只有2 种选择,即装入背包或不装入背包。不能将物品i 装入背包多次,也不能只装入部分的物品i。

0-1 背包问题形式化描述:给定C>0, Wi >0, Vi >0,1≤i≤n,要求n 元0-1向量(  x1 x2 ,…, xn ),xi∈{0,1},1≤i≤n,使得                  达到最大



输入

 第一行有2个正整数n和c。n是物品数,c是背包的容量。接下来的1 行中有n个正整数,表示物品的价值。第3 行中有n个正整数,表示物品的重量。

输出

 计算出装入背包物品的最大价值和最优装入方案。

样例输入

5 10
6 3 5 4 6
2 2 6 5 4

样例输出

15
1 1 0 0 1

提示

 

题目来源

算法设计与实验题解


#include<stdio.h>
#include<stdlib.h>
int f(int c,int n,int *w,int *v,int i,bool *b,bool *mb,int mV){
	if(c<=0 || i==n)
		return mV;
	int p,q;
	b[i]=0;
	p = f(c,n,w,v,i+1,b,mb,mV);
	if(c>w[i]){
		q = f(c-w[i],n,w,v,i+1,b,mb,mV)+v[i];
		if(q>p){
			p=q;
			b[i]=1;
		}
	}
	if(p>mV){
		for(int k=0; k<n; k++)
			mb[i]=b[i];
		mV=p;
	}
	return mV;
}
int main(){
	int n,c,*w,*v,i,mV;
	bool *b,*mb;
	while(scanf("%d%d",&n,&c)==2){
		w=(int*)malloc(sizeof(int)*n);
		v=(int*)malloc(sizeof(int)*n);
		b=(bool*)calloc(n,sizeof(bool));
		mb=(bool*)calloc(n,sizeof(bool));
		for(i=0;i<n;i++)
			scanf("%d",v+i);
		for(i=0;i<n;i++)
			scanf("%d",w+i);
		mV=0;
		mV=f(c,n,w,v,0,b,mb,mV);
		printf("%d\n",mV);
		printf("%d",mb[0]);
		for(i=1;i<n;i++)
			printf(" %d",mb[i]);
		printf("\n");
		free(w);
		free(v);
		free(b);
		free(mb);
	}
}



/*
#include<stdio.h>
#include<stdlib.h>
//c:总容量
//n:物品总个数
//w[i]:第i件物品的重量
//v[i]:第i件物品的价值
//i:当前判断要不要加入到包中的物品下标
//current:当前的存放下标标记
//maxBits:当前最优值得下标
//maxV:当前的最优值
int findMaxV(int c, int n, int *w, int *v, int i, bool *current, bool *maxBits, int maxV){
	if(c<=0 || i==n){
		return maxV;
	}
	int in,out;
	current[i]=0;
	out = findMaxV(c,n,w,v,i+1,current,maxBits,maxV);
	if(c>w[i]){
		in = findMaxV(c-w[i],n,w,v,i+1,current,maxBits,maxV)+v[i];
		if(in>out){
			out=in;
			current[i]=1;
		}
	}
	if(out>maxV){
		for(int k=0; k<n; k++){
			maxBits[i]=current[i];
		}
		maxV=out;
	}
	return maxV;
}

int main(){
	int n,c,*w,*v,i,maxV;
	bool *current,*maxBits;
	while(scanf("%d%d",&n,&c)==2){
		w=(int*)malloc(sizeof(int)*n);
		v=(int*)malloc(sizeof(int)*n);
		current=(bool*)calloc(n,sizeof(bool));
		maxBits=(bool*)calloc(n,sizeof(bool));
		for(i=0;i<n;i++){
			scanf("%d",v+i);
		}
		for(i=0;i<n;i++){
			scanf("%d",w+i);
		}
		maxV=0;
		maxV=findMaxV(c,n,w,v,0,current,maxBits,maxV);
		printf("%d\n",maxV);
		printf("%d",maxBits[0]);
		for(i=1;i<n;i++){
			printf(" %d",maxBits[i]);
		}
		printf("\n");
		free(w);
		free(v);
		free(current);
		free(maxBits);
	}
}
*/






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值