洛谷 P1282 多米诺骨牌

题意简述

给出( a_1,a_2,...,a_n ), ( b_1,b_2,...,b_n )
可以交换( a_i )和( b_i )
求最小的( |(a_1+a_2+...+a_n) - (b_1+b_2+...+b_n)| )需要的最少交换次数

题解思路

dp 表示a数列的和

dp[i][j] = min(dp[i - 1][j - a[i]]);
dp[i][j] = min(dp[i - 1][j - b[i]] + 1);

代码

#include <cstdio>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
int n, s, x, ans1 = INF, ans2 = INF;
int a[2000], b[2000];
int dp[2000][20000];
void mmin(int &x, int y) {x = min(x, y); }
int main()
{
    scanf("%d", &n);
    for (register int i = 1; i <= n; ++i)
    {
        scanf("%d%d", &a[i], &b[i]);
        s += a[i] + b[i];
    }
    for (register int i = 1; i <= n; ++i)
        for (register int j = 0; j <= n * 6; ++j)
            dp[i][j] = INF;
    dp[1][a[1]] = 0;
    dp[1][b[1]] = 1;
    for (register int i = 2; i <= n; ++i)
        for (register int j = 0; j <= n * 6; ++j)
        {
            if (j - a[i] >= 0) mmin(dp[i][j], dp[i - 1][j - a[i]]);
            if (j - b[i] >= 0) mmin(dp[i][j], dp[i - 1][j - b[i]] + 1);
        }
    for (register int i = 0; i <= s; ++i)
        if (dp[n][i] != INF)
        {
            x = abs(s - 2 * i);
            if (ans1 > x) ans1 = x, ans2 = dp[n][i];
            else if (ans1 == x) mmin(ans2, dp[n][i]);
        }
    printf("%d
", ans2);
}
原文地址:https://www.cnblogs.com/xuyixuan/p/9640061.html