CF-480D-Parcels

problem:

http://codeforces.com/problemset/problem/480/D

有一张桌子,和n个物品,要把某些物品彼此压着放在桌子上。

给你n和桌子的承重S

给你n个物品分别的放上去的时间in,拿走的时间out,重量w,承重s,价值v,in<out

对于同一时刻,有多个物品进出的话,顺序随便。

如果他放上桌子,必须在in时间进,放在最上面,out时间出,出的时候他在最上面,并且得到价值v;它可以不放上桌子,得不到价值v

问你最大的可以得到的价值和。

think:

DP。好难的DP。

用两个数组,

f1[N][S] 表示到第i个物品,从他往上所有物品(包括他)重量和不超过S,可以得到的最大价值和。

f2[N][time]表示第i个物品,从他往上所有物品(不包括他)最小进入时间是time,可以得到的最大价值和。

于是f1[i][S] = f2[i][in[i]] + v[i]

对于f2,

f2[i][j] = max(f1[ii][min(S-w[ii], s[ii])] + f2[i][out[i]]) 其中,ii是所有的in[ii] >= in[i] && out[ii] <= in[i]

code:

const int mod = 1000000007;
const int N = 555;
vector<int>st[N<<1];
int in[N], out[N], w[N], s[N], v[N];
int f1[N][N<<1];//承重
int f2[N][N<<1];//时间

int dfs(int i, int S){
    if(S < 0) return 0;
    if(~f1[i][S]) return f1[i][S];
    f2[i][out[i]+1] = 0;
    for(int j = out[i]; j >= in[i]; --j){
        f2[i][j] = f2[i][j+1];
        int len = st[j].size();
        for(int k = 0; k < len; ++k){
            int ii = st[j][k];
            if(out[ii] > out[i] || ii == i) continue;
            f2[i][j] = max(f2[i][j], dfs(ii, min(S - w[ii], s[ii])) + f2[i][out[ii]]);
        }
    }
    return f1[i][S] = f2[i][in[i]] + v[i];
}

int main(){
    int n, S;
    scanf("%d%d", &n, &S);
    for(int i = 1; i <= n; ++i){
        scanf("%d%d%d%d%d", &in[i], &out[i], &w[i], &s[i], &v[i]);
        st[in[i]].PB(i);
    }
    memset(f1, -1, sizeof(f1));
    out[0] = n * 2 + 1;
    in[0] = 0;
    printf("%d\n", dfs(0, S));
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值