B. Shaass and Bookshelf DP

http://codeforces.com/contest/294/problem/B

据说是贪心,我用了一个复杂度是2e8的dp水过去了。

其实这题就是给你n个数,每个数有两个权值,分成两组,使得第一个权值之和,和第二个权值之和的最大值最小。

那么直接设dp[i][j][k][h]表示前i个数中,选了j个,第一个权值的和是k,第二个权值是h,是否可能。

这里是一定要选出n个的,就是n个数都必须使用,才能滚动数组。(把第二维滚动)

如果是从n个数中选出k个,那么就不能滚动了。

那么第一维是01背包直接省略,j那里可以滚动数组。

总复杂度2e8

然后题解是贪心......

还有要注意,k要大于h,就是底下的书要长于上面的书。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;


#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
struct node {
    int ti, wi;
}a[111];
int dp[2][200 + 2][10000 + 2];
void work() {
    int n;
    cin >> n;
    int DFN = 1;
    int sumti = 0, sumwi = 0;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i].ti >> a[i].wi;
        sumti += a[i].ti;
        sumwi += a[i].wi;
    }
    if (n == 1) {
        cout << min(a[1].ti, a[1].wi) << endl;
        return;
    }
//    sort(a + 1, a + 1 + n);
    dp[0][0][0] = DFN;
    int now = 0;
    for (int i = 1; i <= n; ++i) {
        now = !now;
        ++DFN;
        for (int j = sumti; j >= 0; --j) {
            for (int k = sumwi; k >= 0; --k) {
                if (j >= a[i].ti && dp[!now][j - a[i].ti][k] == DFN - 1) {
                    dp[now][j][k] = DFN;
                }
                if (k >= a[i].wi && dp[!now][j][k - a[i].wi] == DFN - 1) {
                    dp[now][j][k] = DFN;
                }
            }
        }
    }
    int ans = inf;
    for (int i = 0; i <= sumti; ++i) {
        for (int j = 0; j <= i; ++j) {
            if (dp[now][i][j] == DFN) {
                ans = min(ans, max(i, j));
            }
        }
    }
    cout << ans << endl;
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    work();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6238454.html