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;
}