Codeforces 1091F New Year and the Mallard Expedition

題面

題意

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章