|BZOJ 1649|二维背包|[Usaco2006 Dec]Cow Roller Coaster

来源:互联网 发布:课时统计软件app 编辑:程序博客网 时间:2024/05/16 19:42

BZOJ 1649
Luogu 2854
from: USACO 2006 Dec Sliver(USACO刷题第10题)

显然是二维费用01背包。
但是直接做会超时,而且还有连接的限制。
根据题意可以知道只有在wi[i]+xi[i]=j才需要考虑转移
那么我们设f[i][j]为铺到i,成本为j的最大有趣值
那么有下列转移方程

f[xi[i]+wi[i]][j]=max(f[xi[i]+wi[i]][j],f[xi[i]][jci[i]]+fi[i])

同时,这样使用会有后效性,我们将数组按照xi排序,接下来按照这个顺序的f[xi[i]]一定是更新完毕的状态,使得无后效性
注意,方程初始化全部为INF,除了f[0][0]=0,因为从f[0][0]转移的状态才是可行的,否则可能会有轨道不连接的问题

#include<cstdio>#include<cstring>#include<algorithm>#include<stack>#include<vector>#define ms(i, j) memset(i, j, sizeof i)#define LL long longusing namespace std;const int MAXN = 10000 + 5, MAXL = 1000 + 5;struct data {    int xi, wi, fi, ci;    bool operator < (const data &b) const {        return xi < b.xi;    }}di[MAXN];int L, n, B;LL f[MAXL][MAXL];//设f[i][j]为铺到i,成本为j void clear() {    ms(f, -127);     f[0][0] = 0;}void init() {    clear();    for (int i=1;i<=n;i++) {        scanf("%d%d%d%d", &di[i].xi, &di[i].wi, &di[i].fi, &di[i].ci);    }    sort(di+1, di+1+n);}void solve() {    LL ans = 0;    for (int i=1;i<=n;i++) {        for (int j=B;j>=di[i].ci;j--) {            f[di[i].xi+di[i].wi][j] = max(f[di[i].xi+di[i].wi][j], f[di[i].xi][j-di[i].ci]+di[i].fi);            ans = max(ans, f[L][j]);        }    }    if (ans>0) printf("%lld\n", ans); else printf("-1\n");}int main() {    #ifndef ONLINE_JUDGE    freopen("1.in", "r", stdin);freopen("1.out", "w", stdout);    #endif    while (scanf("%d%d%d", &L, &n, &B)==3) init(), solve();    return 0;}
原创粉丝点击