题意:
战斗时间取决于你的力量。每场战斗可以用6个参数描述:p1, p2, t1, t2, w1, w2。如果你的力量小于p1,你将输掉战斗;如果你的力量大于p2,需要t2秒赢得战斗;如果力量位于p1和p2(包括p1和p2),战斗时间从t1线性递减到t2。比如p1=50,p2=75,t1=40,t2=15,你的力量为55,则战斗获胜需要35秒。注意,战斗时间可能不是整数。最后两个参数w1和w2分别表示战斗胜利后获得的“加1药”和“乘2药”的数量。注意,你不一定要立刻使用这些补药,可以在需要的时候再用,但不能在战斗中使用补药。
按顺序给出每场战斗的参数,输出赢得所有战斗所需的最短总时间。战斗必须按顺序进行,且不能跳过任何一场战斗。
没想到这道题可以用dfs过,本以为会超时,然而加上剪枝可以过,
if(time>stime)
return;
这个剪枝很巧妙
注意精力大于p2的时候直接赋值时间
#include <iostream>
#include<cstdio>
#include<algorithm>
#include <cmath>
#define imax 1000000005
using namespace std;
int n;
double stime;
struct node
{
int p1,p2,t1,t2,w1,w2;
}a[10005];
int cheng(int s)
{
int sum=1;
if(s==0)
return 1;
for(int i=0;i<s;i++)
sum=sum*2;
return sum;
}
void dfs(int i,int eng,double time,int sum)
{
if(time>stime)
return;
eng=eng+a[i].w1;
int j=0;
if(eng<a[i].p1)
{
for(j=1;j<=a[i].w2+sum;j++)
{
eng=eng*2;
if(eng>=a[i].p1)
break;
}
if(eng<a[i].p1)
{
return;
}
}
sum=sum+a[i].w2-j;
double ttime;
if(i==n-1)
{
eng*=cheng(sum);
if(eng>=a[i].p2)
ttime=a[i].t2;
else
ttime=(a[i].t1-a[i].t2)*(eng-a[i].p1)/(1.0*(a[i].p1-a[i].p2))+a[i].t1;
//cout<<time<<endl;
if(time+ttime<stime)
stime=time+ttime;
return;
}
if(eng>=a[i].p2)
dfs(i+1,eng,time+a[i].t2,sum);
else
{
int teng=eng;
for(int j=0;j<=sum;j++)
{
if(teng>=a[i].p2)
{
dfs(i+1,teng,time+a[i].t2,sum-j);
break;
}
ttime=(a[i].t1-a[i].t2)*(teng-a[i].p1)/(1.0*(a[i].p1-a[i].p2))+a[i].t1;
dfs(i+1,teng,ttime+time,sum-j);
teng=teng*2;
}
}
}
int main()
{
int enge;
while(scanf("%d %d",&n,&enge)&&n!=0)
{
for(int i=0;i<n;i++)
scanf("%d %d %d %d %d %d",&a[i].p1,&a[i].p2,&a[i].t1,&a[i].t2,&a[i+1].w1,&a[i+1].w2);
a[0].w1=0;
a[0].w2=0;
stime=imax;
dfs(0,enge,0,0);
if(stime==imax)
printf("Impossible\n");
else
printf("%.2lf\n",stime);
}
return 0;
}