P1489 猫狗大战
链接
思路
本来想的是:dp[i][j]=min(dp[i-1][j-a[i]]+1)
但是这样有问题:我们这样只能得到前i个,达到空间为j的最小数量
,不是最接近n/2的数量,那么就会错过很多。
所以参考题解之后,总结思想:
dp[i][j]表示达到空间i所用的数量是否可行。这样就可以记录所有的达到某个大小所用的数量,接着根据j == n/2来寻找最少的差值。
代码
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define tin long long
#define itn long long
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int N = 210;
const int M = 8e3 + 10;
int n, sumn;
int a[N];
bool dp[M][N];
void solve()
{
dp[0][0] = 1;
cin >> n;
for (int i = 1; i <= n; i++) { cin >> a[i]; sumn += a[i]; }
for (int i = 1; i <= n; i++)
{
for (int j = M - 1; j >= a[i]; j--)
for (int k = 103; k >= 1; k--)
dp[j][k] |= dp[j - a[i]][k - 1];
}
int t1 = 0, t2 = 1e9;
for (int j = 0; j < M; j++)
{
if (dp[j][n / 2])
{
if (abs(sumn - 2 * j) < abs(t1 - t2))
{
t1 = j, t2 = sumn - j;
}
}
}
if (t1 > t2)swap(t1, t2);
cout << t1 << ' ' << t2;
}
signed main() {
IOS;
solve();
return 0;
}