题面
题意
有一段路要走,路一共有三种类型:草地,水,岩石,在草上可以步行,在水中可以游泳,可以在任何地形上飞,已知每走过1m要花5s但能得到1点能量,每游过1m要花3s但能得到1点能量,每飞过1m要花1s且要耗费1点能量,问走完这段路最少要花所少时间。
做法
首先考虑最简单的走法:在草地上步行,在水中游泳,在石头上飞。这样就会遇到以下两种情况:
1.能量不足,无法飞过岩石。这种情况处理起来相对简单,可以通过在之前出现过的第一段水(如果没有就选择第一段草地)来回走来获得能量。
2.走到终点后能量过多。这就需要将前面的一些草地和水的部分通过方式改为飞行(优先修改草地),具体处理方式是先处理出每段路走完之后到终点至少需要多少能量,若这段路是草地,则与此时能量比较,此时能量减去至少需要能量即为最多消耗的能量。如果这样处理好之后能量还有多,则肯定用来替换游泳,直接计算时间即可。
代码
#include<bits/stdc++.h>
#define ll long long
#define N 100100
using namespace std;
ll n,ans,last=1,num[N],qz[N],to[N],st[N],need[N],fly[N];
char str[N];
int main()
{
ll i,j,p,q,t,tmp;
cin>>n;
for(i=1;i<=n;i++) scanf("%lld",&num[i]),num[i]*=2,qz[i]=qz[i-1]+num[i],st[i]=qz[i]-num[i];
st[n+1]=qz[n];
scanf("%s",str+1);
for(i=q=1,p=0;i<=n;i++)
{
if(str[i]=='L')
{
if(num[i]>p)
{
last=i+1;
t=num[i]-p;
p=0;
if(str[q]=='G') ans+=t*5;
if(str[q]=='W') ans+=t*3;
}
else p-=num[i];
ans+=num[i];
}
else if(str[i]=='W')
{
if(q==1) q=i;
p+=num[i];
ans+=num[i]*3;
}
else
{
p+=num[i];
ans+=num[i]*5;
}
}
for(i=n;i>=last;i--)
{
if(str[i]=='L') need[i-1]=max(num[i],need[i]+num[i]);
else need[i-1]=max(0ll,need[i]-num[i]);
}
for(i=last,t=0;i<=n;i++)
{
if(str[i]=='L') t-=num[i];
else if(str[i]=='W') t+=num[i];
else
{
t+=num[i];
tmp=min(num[i]*2,t-need[i]);
if(tmp<=p)
{
p-=tmp;
fly[i]=tmp/2;
ans-=tmp*2;
t-=tmp;
}
else
{
ans-=p*2;
cout<<ans/2;
return 0;
}
}
}
ans-=p;
cout<<ans/2;
}