BZOJ1334: [Baltic2008]Elect

看上去是个背包

无脑码,样例都过不了

其实他过不了的原因是你先放了一个 很小的物品
又放了一个超过 s/2 的大物品,这样你每次放入背包时,他的转移都是合法的
但是如果你把小的拿掉,显然这个小的物品就是不合法的了

所以要从大到小考虑物品

这样只用在转移的时候保证体积从 s/2 + w[i] to w[i] 枚举就好了


代码:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <cstdio>
using namespace std;

const int MAXN = 305, MAXSIZ = 100005;

int n, tot;
int siz[MAXN];
bool f[MAXSIZ];

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &siz[i]);
        tot += siz[i];
    }
    f[0] = true;
    sort(siz + 1, siz + n + 1);
    for (int i = n; i >= 1; --i) {
        for (int j = min(tot, tot / 2 + siz[i]); j >= siz[i]; --j) {
            f[j] |= f[j - siz[i]];
        }
    }
    int mini = (tot >> 1);
    for (int i = tot; i >= mini; --i) if (f[i]) {
        printf("%d\n", i);
        return 0;
    }
    puts("0");
    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/xcysblog/p/9817557.html