1. 程式人生 > >洛谷 P1800 software_NOI導刊2010提高(06)

洛谷 P1800 software_NOI導刊2010提高(06)

題目連結

題解

二分答案+dp

如果我們知道答案,貪心地想,讓每個人做盡量多的模組一定不會比最優解差

\(f[i][j]\)表示前\(i\)個人第一個模組做了\(j\)塊,第二個模組最多能做多少

然後我們列舉第\(i\)個人做多少塊第一個模組,就可以算出第二個模組最多能做多少

取最大值即可

Code

#include<bits/stdc++.h>
using namespace std;
const int N = 110;
int f[N][N];
int a[N], b[N], n, m;

bool check(int x) {
    memset(f, 128, sizeof(f));
    f[0][0] = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j <= m; j++)
            for (int k = 0; k*a[i] <= x && k <= j; k++)
                f[i][j] = max(f[i][j], f[i-1][j-k]+(x-k*a[i])/b[i]);
    }
    return f[n][m] >= m;
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) scanf("%d%d", &a[i], &b[i]);
    int l = 0, r = 1000000;
    while (l <= r) {
        int mid = (l + r) >> 1;
        if (check(mid)) r = mid-1;
        else l = mid+1;
    }
    printf("%d\n", r+1);
    return 0;
}