Codeforces Round #436 (Div. 2) E fire DP

原题链接:http://codeforces.com/contest/864/problem/E

题目大意:给出n个物品的价值vi,获得该物品所需的时间costi,物品从时间ti开始价值归零。问最多能获得多少总价值的物品,及其解决方案。

首先对于两个物品i,j如果这两个物品都在解集里面,且ti<tj,则先获得物品i一定不会比先获得物品j更劣,

然后对于两个物品i,j如果这两个物品都在解集里面,且ti=tj,vi>vj 则先获得物品i一定不会比先获得物品j更劣,

最后对于两个物品i,j如果这两个物品都在解集里面,且ti=tj,vi=vj ,coti<costj 则先获得物品i一定不会比先获得物品j更劣。

于是就得到了一个优先级的先后顺序,排序后进行DP就可以了。

其中f[ i ] [ j ] 代表到了第 i 个时刻 , 枚举到了第 j 个物品的最大价值。

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline void read(int &x){
    char ch;
    bool flag=false;
    for (ch=getchar();!isdigit(ch);ch=getchar())if (ch=='-') flag=true;
    for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    x=flag?-x:x;
}


inline void read(long long &x){
    char ch;
    bool flag=false;
    for (ch=getchar();!isdigit(ch);ch=getchar())if (ch=='-') flag=true;
    for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    x=flag?-x:x;
}

inline void write(int x){
    static const int maxlen=100;
    static char s[maxlen];
        if (x<0) {   putchar('-'); x=-x;}
    if(!x){ putchar('0'); return; }
    int len=0; for(;x;x/=10) s[len++]=x % 10+'0';
    for(int i=len-1;i>=0;--i) putchar(s[i]);
}

inline void write(long long x){
    static const int maxlen=100;
    static char s[maxlen];
        if (x<0) {   putchar('-'); x=-x;}
    if(!x){ putchar('0'); return; }
    int len=0; for(;x;x/=10) s[len++]=x % 10+'0';
    for(int i=len-1;i>=0;--i) putchar(s[i]);
}

int n;
const int MAXN = 110;
struct zy{
int cost,v,ed,id;
}a[ MAXN ];

bool cmp( zy A, zy B){
if ( A.ed != B.ed )
    return A.ed<B.ed;
if ( A.v != B.v )
    return A.v>B.v;
return A.cost < B.cost ;
}

int f[ 20000 ][100];
pair<int,int> pre[ 20000 ][100];

int kkk[ 20000],cnt;

int main(){
    read(n);
    for (int i=1;i<=n;i++)
    {
        read( a[i].cost);
        read( a[i].ed);
        read( a[i].v);
        a[i].id=i;
    }
    sort( a+1, a+n+1 ,cmp);
    pair<int ,int > ans;
    ans.first=0;
    ans.second=0;
    //for (int i=1;i<=n;i++)
        //printf("v= %d  ed= %d cost=%d\n",a[i].v,a[i].ed,a[i].cost);

    for (int i=1;i<=2000;i++)
        {
            for (int j=1;j<=n;j++)
            if ( a[j].ed >i )
            {
                if ( f[i][j] < f[i-1][j] )
                    {
                        f[i][j]=f[i-1][j];
                        pre[i][j]=make_pair( i-1 , j );
                    }
                if ( i >= a[j].cost )
                {
                    if ( a[j].v > f[i][j] )
                    {
                        f[i][j]=a[j].v;
                        pre[i][j]=make_pair(0,0);
                    }
                    for (int k=1;k<j;k++)
                        if ( f[i-a[j].cost][k]+a[j].v > f[i][j] )
                            {
                                f[i][j]=f[i-a[j].cost][k]+a[j].v;
                                pre[i][j]=make_pair( i-a[j].cost , k );
                            }
                }
            if ( f[ ans.first ][ ans.second ] < f[i][j])
                ans=make_pair( i , j );
            }
        }
    printf("%d\n",f[ans.first][ans.second]);
    while ( ans.second )
        {
            if ( a[ ans.second].id != kkk[ cnt ])
                kkk[++cnt]=a[ ans.second].id;
            ans=pre[ ans.first ][ ans.second ];
        }
    printf("%d\n",cnt);
    for (int i=cnt;i>=1;i--)
        printf("%d ",kkk[i]);
    return 0;
    for (;;)
        {
            int x,y;
            read(x); read(y);
            printf("%d\n",f[x][y]);
        }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/u012602144/article/details/78089784