(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
 

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 (0A 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 
#include 

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;
}








你可能感兴趣的:(acm,ACM——夺金之路)