题意简述
给出( 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);
}