SHAOXIAOJ正在加载中...

2629: 回溯法-01背包问题

金币值:3 定数:7 时间限制:1.000 s 内存限制:128 M
正确:4 提交:4 正确率:100.00% 命题人:
点赞量:0 收藏量:0 题目类型:程序 知识点: 算法设计

题目描述

给定n(1<=n<=20)种物品和一背包,物品i (1≤i≤n) 的重量是wi (wi > 0),其价值为vi (vi > 0),背包的容量为c, 问应如何选择装入背包的物品,使得装入背包中物品的总价值最大? 为了方便编写限界函数,假设按照单位重量获利递减输入每个物品的重量和获利。

测试代码   复制

#include <stdio.h>
// 为了方便编写限界函数,假设按照单位重量获利递减输入每个物品的重量和获利。

int w[21]; //存储物品重量,0号单元不存储有效数据
int v[21]; //存储物品价值,0号单元不存储有效数据
int n;//存储物品个数
int c;//存储背包容量
int bestx[21]; //最优解,0号单元不存储有效数据
int x[21]; //当前解,0号单元不存储有效数据
int bestv;//最优值
int cv;//当前已经放到背包中的物品价值
int cw;//当前已经放到背包中的物品重量

double bound(int i) { //计算剩余物品(i:n)的上界
	int cleft=c-cw;  // 剩余容量
	int b=0;   // b是一个临时变量
	while(i<=n && w[i]<=cleft) {
		cleft-=w[i];
		b+=v[i];
		i++;
	}
	if (i<=n) {
		b+=1.0*v[i]/w[i]*cleft;  // 装满背包
	}
	return b;
}

void backtrack(int i) { // 搜索第i层结点

	if(i>n) { //到达叶结点考虑结束本次递归
		
	} else {
		if(cw+w[i]<=c) {  //搜索左子树,此时必须满足约束函数
			
		}
		if (cv+bound(i+1)>bestv) { //搜索右子树,使用限界函数的目的是为了剪枝,提高算法效率;此处也可以不考虑限界函数。 
			
		}
	}
}

int main(void) {
	scanf("%d %d",&n,&c);
	for(int i=1; i<=n; i++) {
		scanf("%d",&w[i]);
	}
	for(int i=1; i<=n; i++) {
		scanf("%d",&v[i]);
	}
	cw=0;
	cv=0;
	backtrack(1);
	printf("%d\n",bestv);
	for(int i=1; i<=n; i++) {
		printf("%d ",bestx[i]);
	}
	return 0;
}

输入格式

第一行输入两个整数,分别表示n个物品和背包容量c
第二行输入n个整数,分别表示每个物品的重量
第三输入n个整数,分别表示每个物品的价值

输出格式

第一行输出最大价值
第二行输出最解向量的值(1表示放入背包,0表示没有放入背包)

输入样例    复制

3 10
3 4 5
4 5 6

输出样例    复制

11
0 1 1