1. 程式人生 > >nyoj 325 - zb的生日(01揹包)

nyoj 325 - zb的生日(01揹包)

題目連結 http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=325

【題目描述】
今天是陰曆七月初五,acm隊員zb的生日。zb正在和C小加、never在武漢集訓。他想給這兩位兄弟買點什麼慶祝生日,經過調查,zb發現C小加和never都很喜歡吃西瓜,而且一吃就是一堆的那種,zb立刻下定決心買了一堆西瓜。當他準備把西瓜送給C小加和never的時候,遇到了一個難題,never和C小加不在一塊住,只能把西瓜分成兩堆給他們,為了對每個人都公平,他想讓兩堆的重量之差最小。每個西瓜的重量已知,你能幫幫他麼?

輸入
多組測試資料(<=1500)。資料以EOF結尾
第一行輸入西瓜數量N (1 ≤ N ≤ 20)
第二行有N個數,W1, …, Wn (1 ≤ Wi ≤ 10000)分別代表每個西瓜的重量

輸出
輸出分成兩堆後的質量差

樣例輸入
5
5 8 13 27 14

樣例輸出
3

【思路】
0-1揹包,價值和重量相同,揹包重量取總和一半

#include<bits/stdc++.h>
#define umax(a,b)(a>b?a:b)
using namespace std;

const int maxw=200005;

int n;
int w[25];
int dp[maxw];

int main(){
	while(scanf("%d",&n)==1){
		int sum=0;
		for(int i=0;i<n;++i){
			scanf("%d",&w[i]);
			sum+=w[i];
		}
		int c=sum>>1;
		memset(dp,0,sizeof(dp));
		for(int i=0;i<n;++i){
			for(int j=c;j>=w[i];--j){
				dp[j]=umax(dp[j],dp[j-w[i]]+w[i]);
			}
		}
		printf("%d\n",sum-2*dp[c]);
	}
	return 0;
}