CF730J Bottles

\(\mathtt{CF730J}\)

\(\mathcal{Description}\)

\(n\) 瓶水,每瓶水有两个值,剩下的水 \(a_i\) 和这瓶最大的容量 \(b_i\) \((a_i \leq b_i\)。现在要把所有水倒进其中几个瓶子中,是使用的瓶子数量最少。求出最少需要的瓶子和最小要用的时间\((\)\(x\) 单元的水倒进另一个瓶子里需要\(x\) \()\)

\(\mathcal{Solution}\)

第一问要求出最少需要的瓶子很简单,用贪心做,把 \(n\) 瓶水的最大容量排序,要使用的瓶子越大越好,第二问可以用 \(dp\) 做,\(dp[i][j]\) 可以表示选了 \(i\) 个瓶子,容量为 \(j\) 时,水的最大值。
\[ dp[i][j] = max(dp[i][j], dp[i - 1][j - b[k]] + a[k]) \]

\(\mathcal{Code}\)

#include<bits/stdc++.h>
using namespace std;

const int N = 110;

int n, sum, sum1, sum2, num, f[N][N * N];

struct Node {
    int a, b;
} a[N];

inline int read() {
    int x = 0, k = 1; char c = getchar();
    for (; c < 48 || c > 57; c = getchar()) k ^= (c == '-');
    for (; c >= 48 && c <= 57; c = getchar()) x = x * 10 + (c ^ 48);
    return k ? x : -x;
}

inline bool cmp (Node a, Node b) {
    return a.b > b.b || (a.b == b.b && a.a > b.b);
}

int main() {
    n = read();
    for (int i = 1; i <= n; i++)
        a[i].a = read(), sum += a[i].a;
    for (int i = 1; i <= n; i++)
        a[i].b = read(), sum1 += a[i].b;
    std::sort(a + 1, a + 1 + n, cmp);
    for (sum2 = sum; sum > 0; sum -= a[++num].b) ;
    printf("%d ", num);
    memset(f, -0x3f, sizeof(f));
    f[0][0] = 0;
    for (int i = 1; i <= n; i++)
        for (int j = sum1; j >= a[i].b; j--)
            for (int k = 1; k <= num; k++)
                f[k][j] = std::max(f[k][j], f[k - 1][j - a[i].b] + a[i].a);
    int ans = -1;
    for (int i = sum2; i <= sum1; i++)
        ans = std::max(ans, f[num][i]);
    printf("%d\n", sum2 - ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wjnclln/p/11650476.html
730