给我们n个硬币

每个硬币都有它的面值,要我我们分为两堆硬币,使得硬币的差值最小

我们可以dp计算出所有的差值,然后从小到大枚举差值,如果差值存在,就输出

dp[i][j] 表示对于前i件物品能达到差值j

状态转移方程为 if(dp[i-1][j]==1)  dp[i][j] = 1(不选第i个物品),dp[i][abs(j-2*a[i])] = 1(选第i件物品)

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 #include <algorithm>
 5 #include <iostream>
 6 #include <queue>
 7 #include <stack>
 8 #include <vector>
 9 #include <map>
10 #include <set>
11 #include <string>
12 #include <math.h>
13 using namespace std;
14 #pragma warning(disable:4996)
15 typedef long long LL;                   
16 const int INF = 1<<30;
17 /*
18 
19 */
20 const int N = 100 + 10;
21 int a[N];
22 int dp[N][50000+10];//dp[i][j] 表示对于对于前i个物品,差值为j是否存在,  然后算出所有可能的差值 
23 int main()
24 {
25     int t, n, i, j, sum;
26     scanf("%d", &t);
27     while (t--)
28     {
29         scanf("%d", &n);
30         sum = 0;
31         for (i = 1; i <= n; ++i)
32         {
33             scanf("%d", &a[i]);
34             sum += a[i];
35         }
36         
37         memset(dp, 0, sizeof(dp));
38 
39         dp[0][sum] = 1;
40         for (i = 1; i <= n; ++i)
41         {
42             for (j = 0; j <= sum; ++j)
43             {
44                 if (dp[i - 1][j])
45                 {
46                     dp[i][j] = 1;
47                     dp[i][abs(j - 2 * a[i])] = 1;
48                 }
49             }
50         }
51         for (j = 0; j <= sum; ++j)//从小到大枚举差值
52         if (dp[n][j])
53             break;
54         printf("%d\n", j);
55     }
56     return 0;
57 }
View Code

相关文章:

  • 2021-10-07
  • 2021-05-13
  • 2021-07-31
猜你喜欢
  • 2022-12-23
  • 2021-10-17
  • 2021-07-26
  • 2022-12-23
  • 2021-10-07
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案