Codeforces Round #436 (Div. 2) E. Fire(背包+记录路径)

传送门

题意

给出n种物品,抢救第\(i\)种物品花费时间\(t_i\),价值\(p_i\),截止时间\(d_i\)
询问抢救的顺序及物品价值和最大值

分析

\(d_i\)排序的目的是防止以下情况
4 8 100
1 2 100
不排序只能选择第一个物品
(请仔细思考)

那么排序后做一遍背包,排序后选择顺序必定是递增的,求路径时从n往前找,具体见代码

code

#include<bits/stdc++.h>
using namespace std;

#define ll long long
#define F(i,a,b) for(int i=a;i<=b;++i)
#define R(i,a,b) for(int i=a;i<b;++i)
#define mem(a,b) memset(a,b,sizeof(a))

int n;
struct node
{
    int t,d,p,id;
    bool operator<(const node &P)const
    {
        return d<P.d;
    }
}a[101];
int dp[2020];
int vis[101][2020];
vector<int>v;
int main()
{
    cin>>n;
    F(i,1,n) {cin>>a[i].t>>a[i].d>>a[i].p;a[i].id=i;}
    sort(a+1,a+1+n);
    F(i,1,n)
    {
        if(a[i].d<=a[i].t) continue;
        for(int j=a[i].d-1;j>=a[i].t;--j)
        {
            if(dp[j]<dp[j-a[i].t]+a[i].p)
            {
                dp[j]=dp[j-a[i].t]+a[i].p;
                vis[i][j]=1;
            }
        }
    }
    int cost=0,ans=0;
    F(i,1,2000) if(dp[i]>dp[cost]) {ans=dp[i];cost=i;}
    for(int i=n;i;--i) if(vis[i][cost]) v.push_back(a[i].id),cost-=a[i].t;
    int sz=v.size();
    printf("%d\n%d\n",ans,sz);
    for(int i=sz-1;~i;--i) printf("%d%c",v[i],i==0?'\n':' ');
    return 0;
}
posted @ 2017-09-27 16:52  遗风忘语  阅读(123)  评论(0编辑  收藏  举报