题目描述
曹操决定考试时找“鬼才”郭嘉来帮忙作弊,可他突然想起这时郭嘉好像真的成了鬼了,(众所周知,郭嘉死的早)于是干脆让郭嘉在考试时给他托梦,(他负责睡觉^(* ̄(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;
}