Codeforces 864E dp

题意:

房间着火了,里面有n件物品,每件物品有营救需要的时间t,被烧坏的最晚时间d,他的价值p,问能得到的最大价值,并且输出营救出来的物品编号

代码:

//必然是先救存活时间短的即d小的,所以先排个序,dp[i][j]表示枚举到第i件物品时救出他的时间是j时的最大价值,然后就
//是取还是不取这件物品的问题了他的状态是由dp[i-1][~]转移来的。另外这题需要记录取了哪些物品,用g[i][j]表示第i件
//物品在j时间取没取,用pre数组记录前驱。输出还要按照取得顺序输出。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF=0x7fffffff;
int f[109][2009],g[109][2009],pre[109][2009][2];
struct Lu
{
    int t,d,p,id;
    bool operator < (const Lu &x)const{
        return d<x.d;
    }
}L[109];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d%d",&L[i].t,&L[i].d,&L[i].p);
        L[i].id=i;
    }
    sort(L+1,L+1+n);
    memset(g,0,sizeof(g));
    memset(pre,0,sizeof(pre));
    for(int i=1;i<=n;i++){
        for(int j=1;j<=2000;j++){
            f[i][j]=f[i-1][j];
            pre[i][j][0]=i-1;
            pre[i][j][1]=j;
            if(j>=L[i].t&&j<L[i].d){
                if(L[i].p+f[i-1][j-L[i].t]>f[i][j]){
                    f[i][j]=L[i].p+f[i-1][j-L[i].t];
                    g[i][j]=1;
                    pre[i][j][0]=i-1;
                    pre[i][j][1]=j-L[i].t;
                }
            }
        }
    }
    int ans1=-INF,ans2=0;
    for(int i=1;i<=2000;i++){
        if(f[n][i]>ans1){
            ans1=f[n][i];
            ans2=i;
        }
    }
    printf("%d\n",ans1);
    int q[2009],l=0,i=n,j=ans2;
    while(i!=0){
        if(g[i][j]) q[++l]=L[i].id;
        int tmp1=pre[i][j][0];
        int tmp2=pre[i][j][1];
        i=tmp1;j=tmp2;
    }
    printf("%d\n",l);
    for(int i=l;i>=1;i--) printf("%d%c",q[i],i==1?'\n':' ');
    return 0;
}

 

posted @ 2017-09-26 09:31  luckilzy  阅读(410)  评论(0编辑  收藏  举报