題面
題意
有一段路要走,路一共有三種類型:草地,水,岩石,在草上可以步行,在水中可以游泳,可以在任何地形上飛,已知每走過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;
}