[Poi 2012] bzoj2794 Cloakroom [dp]

Description:
n件物品,每件物品有三个属性a[i],b[i],c[i](a[i]<b[i])
再给出q个询问,每个询问由非负整数m,k,s组成,问是否能够选出某些物品使得:
1. 对于每个选的物品i,满足a[i]<=mb[i]>m+s
2. 所有选出物品的c[i]的和正好是k


Solution:
先按a离线排序,现在问题在于b。那么我们用c做背包,求出b的最大最小值即可。


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e6 + 5;
struct data_1 {
    int a, b, c;
    bool friend operator < (const data_1 &a, const data_1 &b) {
        return a.a < b.a;
    }
} a[maxn];
struct data_2 {
    int m, s, k, id;
    bool friend operator < (const data_2 &a, const data_2 &b) {
        return a.m < b.m;
    }
} b[maxn];
int n, m;
int dp[maxn], ans[maxn];
int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) {
        scanf("%d%d%d", &a[i].c, &a[i].a, &a[i].b);
    }
    sort(a + 1, a + n + 1);
    scanf("%d", &m);
    for(int i = 1; i <= m; ++i) {
        scanf("%d%d%d", &b[i].m, &b[i].k, &b[i].s);
        b[i].id = i;
    }
    sort(b + 1, b + m + 1);
    dp[0] = 1e9;
    for(int i = 1, j = 0; i <= m; ++i) {
        while(j < n && b[i].m >= a[j + 1].a) {
            ++j;
            for(int k = 100000; k >= a[j].c; --k) {
                dp[k] = max(dp[k], min(dp[k - a[j].c], a[j].b));
            }
        }
        if(dp[b[i].k] > b[i].m + b[i].s) {
            ans[b[i].id] = 1;
        }
    }
    for(int i = 1; i <= m; ++i) {
        puts(ans[i] ? "TAK" : "NIE");
    }
    return 0;
}
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页