D - President - 背包dp

D - President - 背包dp_第1张图片

 D - President - 背包dp_第2张图片

 D - President - 背包dp_第3张图片

 D - President - 背包dp_第4张图片

 分析:

        需要让所有x大于y的对应的z的总数大于z总共的数量的一半,找最小需要转化的数量,那么可以转化为01背包问题,z作为体积,每组的x和y都可以计算出一个值表示需不需要转化,作为背包价值,如果x大于y那么一定价值是0,否则至少需要(y - x) / 2 + 1数量转化,那么就转化成了背包dp,然后因为只要大于等于z总数的一半都可以符合,所以最后对满足的所有情况取最小值。

代码:

       

#include 

using namespace std;
using ll = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;
    vector x(n + 1), y(n + 1), z(n + 1);
    ll m = 0;
    for(int i = 1; i <= n; i ++) {
        cin >> x[i] >> y[i] >> z[i];
        m += z[i];
    }
    vector f(m + 1, 1e17);
    f[0] = 0;
    for(int i = 1; i <= n; i ++) {
        ll w = 0;
        if(y[i] > x[i]) w = (y[i] - x[i]) / 2 + 1;
        for(int j = m; j >= z[i]; j --) {
            f[j] = min(f[j], f[j - z[i]] + w);
        }
    }
    ll ans = 1e17;
    for(int i = m / 2 + 1; i <= m; i ++) ans = min(ans, f[i]);
    cout << ans << '\n';
}

你可能感兴趣的:(算法,c++,思维,dp)