Vijos P1153 - 猫狗大战

题意

把给定的数分成两部分,最多只能相差1个,使得他们的差最小。

思路

记得在UVa上有一题,分成两部分使得差最小,那直接对sum的一半进行背包即可,这题算是那题的升级版吧。

dp[i][j][k]表示前i个选j个能否到达k,数据太大,滚一下。


又看到一种思路,先把输入分两部分存起来,然后用一个二重for,如果能够使相差减少就交换。

代码

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define MP(a, b) make_pair(a, b)
const int MAXN = 200 + 10;
const int INF = 0x3f3f3f3f;

int w[MAXN];
bool dp[MAXN][MAXN * 40 + 10];

int main()
{
    //freopen("input.txt", "r", stdin);
    int n, i, j, sum = 0;
    scanf("%d", &n);
    for (i = 1; i <= n; i++)
    {
        scanf("%d", &w[i]);
        sum += w[i];
    }
    dp[0][0] = 1;
    for (i = 1; i <= n; i++)
        for (j = n; j >= 1; j--)
            for (int k = sum; k >= w[i]; k--)
                dp[j][k] |= dp[j - 1][k - w[i]];
    int t = sum >> 1;
    n >>= 1;
    for (i = t; i >= 0; i--)
        if (dp[n][i])
        {
            printf("%d %d\n", i, sum - i);
            return 0;
        }
    return 0;
}




 
 
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define LL long long
  4. #define MP(a, b) make_pair(a, b)
  5. const int MAXN = 200 + 10;
  6. const int INF = 0x3f3f3f3f;
  7. int w[MAXN], d[MAXN];
  8. int main()
  9. {
  10. //freopen("input.txt", "r", stdin);
  11. int n, i, j, asum = 0, bsum = 0, minmin = INF;
  12. scanf("%d", &n);
  13. for (i = 1; i <= n / 2; i++)
  14. {
  15. scanf("%d", &w[i]);
  16. asum += w[i];
  17. }
  18. int t = n - n / 2;
  19. for (i = 1; i <= t; i++)
  20. {
  21. scanf("%d", &d[i]);
  22. bsum += d[i];
  23. }
  24. minmin = abs(asum - bsum);
  25. for (i = 1; i <= n / 2; i++)
  26. for (j = 1; j <= t; j++)
  27. if (abs(bsum - asum + 2 * (w[i] - d[j])) < minmin)
  28. {
  29. asum += d[j] - w[i];
  30. bsum += w[i] - d[j];
  31. minmin = abs(asum - bsum);
  32. swap(w[i], d[j]);
  33. }
  34. printf("%d %d\n", min(asum, bsum), max(asum, bsum));
  35. return 0;
  36. }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值