2017/9/26Codeforces E题

来源:互联网 发布:怎么投诉举报淘宝卖家 编辑:程序博客网 时间:2024/05/16 12:21

2017/9/26Codeforces E题

我终于打了一场cf了,可惜我太蒟蒻,6题才出了4题,反思一下,订正一下吧
E题面:http://codeforces.com/contest/864/problem/E
E题大意:
Polycarp家着火了,现在Polycarp要把一些东西救出来,每样东西都有三个值ti(救出来所花的时间),di(物品被烧毁的时间,只有物品在被烧毁前救出来才有价值),pi(物品价值)
输入:一个N(1≤N≤100),之后N行每行三个数ti(1≤ti≤20),di(1≤di≤2000),pi(1≤pi≤20)
输出:第一行是最大救出的价值,第二行输出被救出的物品数量,第三行按被救顺序输出每个物品的编号(编号为物品输入顺序),若有多种方案则输出一种

样例输入1
3
3 7 4
2 6 5
3 7 6
样例输出1
11
2
2 3
样例输入2
2
5 6 1
3 3 5
样例输出2
1
1
1

题目不难,想一想O(n^2)能过,刚开始看想个背包,然后呢发现,好像就是啊,只是物品会被烧毁,那么就大力DP一发吧
既然是想O(n^2)的转移,那么一维转移物品一维用作时间
f[i]表示到第i的时间所获取的价值最大值
状态转移

f[i]=max(f[it[a]]+p[a])(1aNd[a]>f[i])

是不是感觉很easy?
然而,要怎么样放才能保证转移不因为被烧毁时间而挂掉呢
由于我偷懒,所以在考场上我按di-ti排序,然后成功WA
为什么呢?因为有这样的情况:
p1=8 , d1=10,p1=10
p2=1 , d2=4 , p2=10
答案是20我的程序输出10
那怎么办呢?
直接按di排序就好啦
为什么呢?
假设两个物品a,b能同时救出,那么一定满足这个情况

若a被摧毁时间比b早
这里写图片描述
若a被摧毁时间比b晚
这里写图片描述
(因为保证能同时存在所以b被摧毁的时间一定在a、b被救出来之后)
然后就好啦
放一下代码

#include<cstdio>#include<cstring>#include<algorithm>using namespace std; inline void read(int&x){    char cu=getchar();x=0;bool fla=0;    while(cu<'0'||cu>'9'){if(cu=='-')fla=1;cu=getchar();}    while('0'<=cu&&cu<='9')x=x*10+cu-'0',cu=getchar();    if(fla)x=-x; }void printe(const int x){    if(x>=10)printe(x/10);    putchar(x%10+'0');}inline void print(const int x){    if(x<0)putchar('-'),printe(-x);    else printe(x);}int N;struct things{    int t,d,p,ended,id;//在ended时刻之前救该物品才有效,id即编号 }t[101];int cmp(things x,things y){    return x.d<y.d;}int dp[2001],from[2001][2001],ans=-1,wz; int main(){    memset(dp,-1,sizeof(dp));    read(N);    for(int i=1;i<=N;i++)        read(t[i].t),read(t[i].d),read(t[i].p),t[i].id=i;    sort(t+1,t+N+1,cmp);//排序,尤其注意     for(int i=1;i<=N;i++)t[i].ended=t[i].d-t[i].t;//算出ended     dp[0]=0;    for(int i=1;i<=N;i++)    {        if(t[i].ended<=0)continue;//特判         for(int j=t[i].ended-1;j>=0;j--)        {            if(dp[j]==-1)continue;//特判             if(dp[j]+t[i].p>dp[j+t[i].t])            {                dp[j+t[i].t]=dp[j]+t[i].p;//转移                 memcpy(from[j+t[i].t],from[j],sizeof(from[j+t[i].t]));                 from[j+t[i].t][++from[j+t[i].t][0]]=t[i].id;//更新             }        }    }    for(int i=0;i<=2000;i++)//找出答案         if(dp[i]>ans)        {            ans=dp[i];            wz=i;        }    print(ans);    putchar('\n');    print(from[wz][0]);    putchar('\n');    if(from[wz][0]!=0)    {        print(from[wz][1]);        for(int i=2;i<=from[wz][0];i++)putchar(' '),print(from[wz][i]);    }    return 0;}
原创粉丝点击