P1489 猫狗大战

链接

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;
}
posted @ 2025-07-10 10:07  WHUStar  阅读(6)  评论(0)    收藏  举报