题目描述
http://codeforces.com/contest/480/problem/D
DP
区间DP是可行的,但是是4*n^2*S,亲测过不了。
然后n^2*S的看这个
http://blog.csdn.net/keshuai19940722/article/details/40720965
区间DP:
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
#define max(a,b) (a>b?a:b)
using namespace std;
const int maxn=1000+10;
int f[maxn][maxn*2],g[maxn][maxn*2],dis[maxn][maxn],p[maxn][maxn*2];
int a[maxn],b[maxn],w[maxn],s[maxn],v[maxn],sum[maxn],num[maxn];
int h[maxn],go[maxn],next[maxn],c[maxn*2];
int i,j,k,l,x,y,t,n,m,tot,top,ans,mx,mi;
void add(int x,int y){
go[++tot]=y;
next[tot]=h[x];
h[x]=tot;
}
int main(){
scanf("%d%d",&n,&m);
mi=2*n;
fo(i,1,n){
scanf("%d%d%d%d%d",&a[i],&b[i],&w[i],&s[i],&v[i]);
a[i]++;b[i]++;
c[++top]=a[i];
}
sort(c+1,c+top+1);
top=unique(c+1,c+top+1)-c-1;
fo(i,1,n) a[i]=lower_bound(c+1,c+top+1,a[i])-c;
top=0;
fo(i,1,n) c[++top]=b[i];
top=unique(c+1,c+top+1)-c-1;
fo(i,1,n) b[i]=lower_bound(c+1,c+top+1,b[i])-c;
fo(i,1,n){
mx=max(mx,b[i]);
mi=min(mi,a[i]);
dis[a[i]][b[i]]=i;
add(a[i],i);
}
fd(i,n,1){
fo(j,1,n)
fo(k,0,m)
f[j][k]=0;
fo(j,1,n){
x=dis[i][j];
if (x){
t=min(s[x],m-w[x]);
fd(k,t,0){
if (k<=s[x]) g[j][k+w[x]]=max(g[j][k+w[x]],g[j][k]+v[x]);
}
}
fo(k,0,m){
g[j+1][k]=max(g[j+1][k],g[j][k]);
}
fo(k,0,m){
f[j][k]=max(f[j][k],g[j][k]);
}
t=h[j];
while (t){
y=go[t];
sum[0]=g[j][0];
fo(k,1,m) sum[k]=max(sum[k-1],g[j][k]);
num[0]=p[y][0];
fo(k,1,m) num[k]=max(num[k-1],p[y][k]);
fo(k,0,m){
g[b[y]][k]=max(g[b[y]][k],g[j][k]+num[k]);
g[b[y]][k]=max(g[b[y]][k],p[y][k]+sum[k]);
}
t=next[t];
}
if (x)
fo(k,0,m) p[x][k]=g[j][k];
}
fo(j,1,n)
fo(k,0,m)
g[j][k]=f[j][k],ans=max(ans,g[j][k]);
}
printf("%d\n",ans);
}
AC的
#include <cstdio>
#include <algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=500+10;
struct dong{
int in,out,w,s,v;
void read(){
scanf("%d%d%d%d%d",&in,&out,&w,&s,&v);
}
friend bool operator <(dong a,dong b){
return a.out<b.out||a.out==b.out&&a.in>b.in;
}
} p[maxn];
int dp[maxn][maxn*2],f[maxn*2];
int i,j,k,l,t,w,o,wi,n,m;
int main (){
scanf("%d%d",&n,&m);
p[0]=(dong){0,2*maxn,0,m,0};
fo(i,1,n) p[i].read();
sort(p,p+n+1);
fo(i,0,n){
fo(j,p[i].w,m){
k=p[i].in;
t=min(p[i].s,j-p[i].w);
f[k]=0;
fo(l,0,i-1)
if (p[l].in>=p[i].in){
while (k<p[l].out){
k++;
f[k]=f[k-1];
}
f[k]=max(f[k],f[p[l].in]+dp[l][t]);
}
dp[i][j]=f[k]+p[i].v;
}
}
printf("%d\n",dp[n][m]);
}