UVa 562

  题目大意:有n(n <= 100)个硬币,每个硬币的面额为1到500分,现在让你将这些硬币分成俩份,使得这俩份的硬币总额的差最小。

  0-1背包问题,计算出所用硬币的总额sum,平均值aver = floor(sum/2),实际上是计算小于等于aver的最大可分配金额。dp[i][j]表示只处理前i个硬币并且总金额小于等于j的金额总数。状态转移方程:dp[i][j] = max(dp[i-1][j], dp[i-1][j-a[i]] + a[i])。

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 int dp[110][25100];
 6 int a[110];
 7 int main()
 8 {
 9 #ifdef LOCAL
10     freopen("in", "r", stdin);
11 #endif
12     int T;
13     scanf("%d", &T);
14     while (T--)
15     {
16         int n;
17         scanf("%d", &n);
18         int sum = 0;
19         for (int i = 1; i <= n; i++)
20         {
21             scanf("%d", &a[i]);
22             sum += a[i];
23         }
24         int aver = sum / 2;
25         for (int i = 0; i <= aver; i++)
26             dp[0][i] = 0;
27         for (int i = 1; i <= n; i++)
28             for (int j = 0; j <= aver; j++)
29             {
30                 dp[i][j] = dp[i-1][j];
31                 if (j >= a[i])
32                     dp[i][j] = max(dp[i][j], dp[i-1][j-a[i]]+a[i]);
33             }
34         printf("%d
", sum - dp[n][aver]*2);
35     }
36     return 0;
37 }
38 
39             
View Code
原文地址:https://www.cnblogs.com/xiaobaibuhei/p/3305535.html