(hdu step 3.3.1)Big Event in HDU(01背包:N件物品放在容量为V的背包中,第i件物品的费用是c[i],价值是w[i]。问所能获取的最大价值)

Big Event in HDU

Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 854 Accepted Submission(s): 345

Problem Description
Nowadays, we all know that Computer College is the biggest department in HDU. But, maybe you don't know that Computer College had ever been split into Computer College and Software College in 2002.
The splitting is absolutely a big event in HDU! At the same time, it is a trouble thing too. All facilities must go halves. First, all facilities are assessed, and two facilities are thought to be same if they have the same value. It is assumed that there is N (0<N<1000) kinds of facilities (different value, different kinds).
 

Input
Input contains multiple test cases. Each test case starts with a number N (0 < N <= 50 -- the total number of different facilities). The next N lines contain an integer V (0<V<=50 --value of facility) and an integer M (0<M<=100 --corresponding number of the facilities) each. You can assume that all V are different.
A test case starting with a negative integer terminates input and this test case is not to be processed.
 

Output
For each case, print one line containing two integers A and B which denote the value of Computer College and Software College will get respectively. A and B should be as equal as possible. At the same time, you should guarantee that A is not less than B.
 

Sample Input
2
10 1
20 1
3
10 1 
20 2
30 1
-1
 

Sample Output
20 10
40 40
 

Author
lcy


题目分析

                         这是属于背包九讲中的《01 背包》。所谓的01背包,也就是说每种物品只有两种状态,放或者不放。这道题中,只要求出了software college所能获取的最大价值,那么computer college所能获取的最大价值也就知道了。所以将software college所能获取的最大价值sum/2设为背包的最大容量V。在这道题中,每件物品的价值w[i]同样作为了费用c[i]。。。。只要明白以上的思路,想必编码也就不困难了。。。



代码如下:

/*
 * a.cpp
 *
 *  Created on: 2015年2月12日
 *      Author: Administrator
 */

#include <iostream>
#include <cstdio>

using namespace std;

const int maxn = 5005;
const int maxm = 250005;
int w[maxn];//用于记录每种物品的价值
int f[maxm];//用于记录容量为v时所能获取的最大价值

int main() {
	int n;
	while (scanf("%d", &n) != EOF, n > 0 ) {//对于n为-1时结束的处理为n>0

		memset(w,0,sizeof(w));//重置费用/价值为0。其实在这里重不重置都没有影响
		memset(f,0,sizeof(f));//重置充值或能获取的最大价值为0。这个数组一定要重置,否则可能影响状态转移方程f[v] = max(f[v],f[v - c[i]] + w[i]);


		int v, m;
		int sum = 0;//所有商品的总价值
		int i;
		int j;
		int cnt = 0;
		for (i = 0; i < n; ++i) {//遍历每种物品
			scanf("%d%d", &v, &m);

			sum += v*m;//将每种物品的总价值加到所有商品的总价值中

			for (j = 0; j < m; ++j) {
				w[cnt++] = v;//记录每一种物品的价值
			}
		}

		cnt -= 1;

		for (i = 0; i < cnt; ++i) {
			for (j = sum / 2; j >= w[i]; --j) {
				/**
				 * 将其展开为f[i][j] = max(f[i-1][j],f[i-1][j-w[i]]+w[i])来理解
				 * 即:前i件物品放在容量为j的背包时所能获取的最大价值是
				 * 第i-1件物品放在容量j的背包中所能获得最大值(不放第i件物品在背包中)与
				 * 第i-1件物品放在容量为j-w[i]的背包中所能达到的最大值(这是腾出地方放第i件物品)
				 * 中的最大值
				 */
				f[j] = max(f[j], f[j - w[i]] + w[i]);
			}
		}

		//一个学院能获取的价值是f[sum / 2],那么另一个能获取的自然是sum - f[sum / 2]了
		printf("%d %d\n", sum - f[sum / 2], f[sum / 2]);
	}

	return 0;
}








  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
问题描述: 假设有一个能装入总体积为T的背包和n件体积分别为w1 , w2 , … , wn 的物品,能否从n件物品挑选若干件恰好装满背包,即使w1 +w2 + … + wn=T,要求找出所有满足上述条件的解。例如:当T=10,各件物品的体积{1,8,4,3,5,2}时,可找到下列4组解: (1,4,3,2) (1,4,5) (8,2) (3,5,2)。 问题提示: 可利用回溯法的设计思想来解决背包问题。首先将物品排成一列,然后顺序选取物品装入背包,假设已选取了前i 件物品之后背包还没有装满,则继续选取第i+1件物品,若该件物品"太大"不能装入,则弃之而继续选取下一件,直至背包装满为止。但如果在剩余的物品找不到合适的物品以填满背包,则说明"刚刚"装入背包的那件物品"不合适",应将它取出"弃之一边",继续再从"它之后"的物品选取,如此重复,直至求得满足条件的解,或者无解。 题目之二: 问题描述: 假设有n件物品,这些物品的重量分别是W1 , W2 , … , Wn,物品的价值分别是V1,V2, …,Vn。求从这n件物品选取一部分物品的方案,使得所选的物品的总重量不超过限定的重量W(W<∑Wi, i=1,2,┅,n),但所选的物品价值之和为最大问题提示: 利用递归寻找物品的选择方案。假设前面已有了多种选择的方案,并保留了其价值最大的方案于数组option[],该方案的总价值保存于变量max_value。当前正在考察新方案,其物品选择情况保存于数组eop[]。假设当前方案已考虑了i-1件物品,现在要考虑第i件物品:当前方案已包含的物品的重量之和为tw;因此,若其余物品都选择是可能的话,本方案所能达到的总价值的期望值设为tv。引入tv是当一旦当前方案的总价值的期望值也小于前面方案的总价值max_value时,继续考察当前方案已无意义,应终止当前方案而去考察下一个方案。 第i件物品的选择有两种可能: ① 物品i被选择。这种可能性仅当包含它不会超过方案总重量的限制才是可行的。选之后继续递归去考虑其余物品的选择; ② 物品i不被选择。这种可能性仅当不包含物品i也有可能找到价值更大的方案的情况。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

帅气的东哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值