弱校胡策 深渊

来源:互联网 发布:软件著作权申请要求 编辑:程序博客网 时间:2024/04/29 13:28

题目描述
曹操决定考试时找“鬼才”郭嘉来帮忙作弊,可他突然想起这时郭嘉好像真的成了鬼了,(众所周知,郭嘉死的早)于是干脆让郭嘉在考试时给他托梦,(他负责睡觉^(* ̄(oo) ̄)^)由于曹操睡觉打呼的声音吵到了别人,所以天道将他丢入了了梦之深渊,深渊的深度为D,而且在这里几乎任何东西都会很快被吞噬,幸好曹操有诸侯称号护体,暂时不会被吞噬,可称号只能帮他维持10s的时间。于是郭嘉从地狱带来了深渊币,并会在约定好的时间将深渊币投入深渊。曹操可以用深渊币回复称号能力(无上限)或者转化成可以存在于深渊的天梯,但深渊币也不尽相同(即转化的天梯高度和恢复的能量可能不同),若曹操与郭嘉会和将一定能考满分,而曹操一定会采取最佳策略,汉献帝刘协想知道曹操从梦中出来的时间,以便破坏这次见面,但由于手
下无可用之才,于是找到了你……
输入描述
第一行为2个整数, D 和 G (1 <= G <= 100), G为被投入深渊的深渊币的数量。
第二到第G+1行每行包括3个整数: T (0 < T <= 1000),表示深渊币被投进井中的时间;
F (1 <= F <= 30),表示该深渊币能恢复曹操称号能力的时间;和 H (1 <= H <= 25),该深渊币转化成的天梯的高度。输出描述 如果曹操可以走出深渊,输出一个整数表示最早什么时候可以走出;否则输出曹操最长可以存活多长时间。
样例输入
20 4
5 4 9
9 3 2
12 6 10
13 1 1
样例输出
13

题目来源:http://codevs.cn/problem/1684/

60分:爆搜+一些不知是否有用的小优化

#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;const int maxn=2000005;struct dqs{    int tim,hf,tt;}hh[maxn];  int d,g,flag=0;bool cmp(dqs a,dqs b){    if(a.tim==b.tim)    {        if(a.hf==b.hf) return a.tt<b.tt;        return a.hf<b.hf;    }    return a.tim<b.tim;}void dfs(int i,int pret,int preh){    if(flag==2) return;    else if(i>g) return;    else if(hh[i].tim>pret) return;    else    {        preh+=hh[i].tt;        if(preh>=d)        {            flag=2;            printf("%d\n",hh[i].tim);            return;        }        dfs(i+1,pret,preh);        preh-=hh[i].tt;        dfs(i+1,pret+hh[i].hf,preh);    }}int main(){    scanf("%d%d",&d,&g);    for(int i=1;i<=g;i++)        scanf("%d%d%d",&hh[i].tim,&hh[i].hf,&hh[i].tt);    sort(hh+1,hh+g+1,cmp);    int sj=10;    for(int i=1;i<=g;i++)   //最长存活     {        if(sj<hh[i].tim)        {        //  cout<<i<<" "<<hh[i].tim<<endl;            flag=1;        //  cout<<"11111"<<endl;            printf("%d\n",sj);            break;        }        else sj+=hh[i].hf;    }    if(flag==0)    {        int tmp=0;        for(int i=1;i<g;i++)            tmp+=hh[i].tt;        if(tmp<d)            printf("%d\n",sj);        else        {            dfs(1,10,0);        //  cout<<flag<<" 2222"<<endl;            if(flag!=2)                printf("%d\n",sj);          }    }    return 0;}

100分:
利用01背包变形。
以下来自loi_wzhd的题解分析:
在这道题中,由于时间在不断变化的过程中,曹操的能量会不断减少,所以使得这道题看起来会很麻烦。那么,如何处理时间的问题呢?
实际上,我们并不需要每次把时间都减去这些能量,只需要判断总能量与时间大小关系就知道曹操是否会被吞噬。
既然不需要减去能量,我们只需要记录到达某一高度的最大能量值就可以了。
这就成了01背包的变形。
高度就是背包的容积,能量就是背包的价值。
不同的是,在这道题中,要先按照时间排一遍序,(题目并没有说一定按照时间先后给你物品),并且在某高度下,只有曹操能活到那个时间才能够使用这个物品(特判一下物品的价值是否大于等于时间)。

#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;const int maxn=2000005;struct dqs{    int tim,hf,tt;}hh[maxn];int dp[maxn];int d,g;bool cmp(dqs a,dqs b){    if(a.tim==b.tim)    {        if(a.hf==b.hf) return a.tt<b.tt;        return a.hf<b.hf;    }    return a.tim<b.tim;}int main(){    scanf("%d%d",&d,&g);    for(int i=1;i<=g;i++)        scanf("%d%d%d",&hh[i].tim,&hh[i].hf,&hh[i].tt);    sort(hh+1,hh+g+1,cmp);    dp[0]=10;    for(int i=1;i<=g;i++)    {        for(int j=d;j>=0;j--)        {            if(dp[j]>=hh[i].tim)            {                if(j+hh[i].tt>=d)                {                    printf("%d\n",hh[i].tim);                    return 0;                }                dp[j+hh[i].tt]=max(dp[hh[i].tt+j],dp[j]);                dp[j]+=hh[i].hf;            }        }    }    printf("%d\n",dp[0]);       return 0;}