弱校胡策 深淵

題目描述
曹操決定考試時找“鬼才”郭嘉來幫忙作弊,可他突然想起這時郭嘉好像真的成了鬼了,(衆所周知,郭嘉死的早)於是乾脆讓郭嘉在考試時給他託夢,(他負責睡覺^(* ̄(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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章