Codeforces 1091F New Year and the Mallard Expedition

190 篇文章 2 订阅
24 篇文章 0 订阅

题面

题意

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值