(背包dp)UVA - 562 Dividing coins

题意:有n个硬币,每个硬币有个价值,两个人分配硬币,要求最公平分配时候两人拿到的钱的差。


分析:很明显,两人拿到的钱的差越小越公平。

一开始想,一定是一人一半最公平,所以直接把总和sum/2,对着half跑01背包,但是WA了,修改后分别讨论奇偶,额外进行一次sum-half的01背包,也WA,仔细想想觉得有些漏洞,可能有些东西还没考虑到。

干脆想直接跑完整的背包试试,

结果,这题其实可以干脆直接跑sum的背包,不断更新ans=min(ans,sum-dp[j]*2)就行了。如果ans==inf,表示不能分,也就是1个,这时输出0。


代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<set>
 7 #include<vector>
 8 #include<queue>
 9 #include<map>
10 #include<list>
11 #include<bitset>
12 #include<string>
13 #include<cctype>
14 #include<cstdlib>
15 
16 using namespace std;
17 
18 typedef long long ll;
19 typedef unsigned long long ull;
20 
21 int t;
22 const int inf=1<<30;
23 const int maxn=100*501;
24 int dp[maxn];
25 int val[110];
26 
27 void solve() {
28     scanf("%d",&t);
29     while(t--) {
30         int n;
31         int sum=0;
32         memset(dp,0,sizeof(dp));
33         scanf("%d",&n);
34         for(int i=0; i<n; i++) {
35             scanf("%d",&val[i]);
36             sum+=val[i];
37         }
38         int half=sum/2;
39         int ans=inf;
40         for(int i=0; i<n; i++) {
41             for(int j=sum; j>=val[i]; j--) {
42                 dp[j]=max(dp[j],dp[j-val[i]]+val[i]);
43                 ans=min(ans,abs(sum-dp[j]*2));
44             }
45         }
46         if(ans==inf)puts("0");
47         else printf("%d\n",ans);
48 
49     }
50 }
51 
52 
53 
54 int main() {
55 
56 #ifndef ONLINE_JUDGE
57     freopen("in.txt", "r", stdin);
58     freopen("out.txt", "w", stdout);
59 #endif
60     //iostream::sync_with_stdio(false);
61     solve();
62     return 0;
63 }

 

posted @ 2016-09-01 22:01  tak_fate  阅读(241)  评论(0编辑  收藏  举报