Codeforces 1091F

Good Bye 2018 F. New Year and the Mallard Expedition


题意

一只鸭子想从数轴的左端走到右端

数轴上有三种环境:草原Grass,水Water,岩浆Lava

给定一个长度为(n)的字符串,表示自左向右的环境分布

再给定一个长度为(n)的数组,表示每种环境占的宽度

在草原上,鸭子只能走或者飞

在水上,鸭子只能游或者飞

在岩浆上,鸭子只能飞

鸭子走的速度为一米(5)秒,游的速度为一米(3)秒,飞的速度为一米(1)

同时,鸭子每走一米或者游一米可以积攒(1)个单位的体力,飞一米需要消耗(1)个单位的体力

鸭子不需要严格移动整数距离,比如宽度为(5)的草原可以走(2.5)米飞(2.5)

鸭子也可以往回走或者游,用于积攒体力

初始时鸭子体力为(0),问从左端走到右端的最短时间,保证题目有解(即第一种环境一定不是岩浆)


限制

(1leq nleq 10^5)

(1leq l_ileq 10^{12})




思路

贪心模拟

假设目前我们需要经过一段长度为(len)的区域

方法有:

  • 草原限定:走(frac {len} 2)米,飞(frac {len} 2)米,时间消耗(5*frac {len} 2+1*frac {len} 2=3*len)
  • 水域限定:走(frac {len} 2)米,飞(frac {len} 2)米,时间消耗(3*frac {len} 2+1*frac {len} 2=2*len)
  • 如果在这之前有水域是飞行经过的,那么可以将某一段从飞行改成游泳,每米将会多使用(3-1=2)秒的时间,但能量会从(-1)变成(+1),所以时间消耗(frac{(3-1)*len}{2}+1*len=2*len)
  • 如果在这之前有草原是飞行经过的,那么可以将某一段从飞行改成走路,每米将会多使用(5-1=4)秒的时间,但能量会从(-1)变成(+1),所以时间消耗(frac{(5-1)*len}{2}+1*len=3*len)
  • 如果之前有经过水域,那么可以让鸭子往回游积攒体力,时间消耗为(3*len+1*len=4*len)
  • 如果之前有经过草原,那么可以让鸭子往回走积攒体力,时间消耗为(5*len+1*len=6*len)

所以对于本题,需要使用(isWater)(isGrass)记录某个位置之前是否存在水域或者草原

使用(flyWater)(flyGrass)记录某个位置之前在水域上飞行了多少米,在草原上飞行了多少米(也就是有多少米能用来更改)

所以可以进行模拟——

  • 如果当前是草原,那么检查是否前面的水域中存在飞行经过的区域(因为将飞行改成游泳(2*len)比直接走并飞行(3*len)所花的时间少),再直接走并飞行
  • 如果当前是水域,那么直接走并飞行((2*len)已经是最短时间了)
  • 如果当前是岩浆,根据花费的时间排序((2lt3lt4lt6)),先判断并将某一段从飞行改成游泳,再判断并将某一段从飞行改成走路,再尝试让鸭子往回游积攒体力,最后尝试让鸭子往回走积攒体力



程序

(343ms/1000ms)

//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/hash_policy.hpp>
#include<bits/stdc++.h>
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
#define pb push_back
#define eb emplace_back
#define mst(a,b) memset(a,b,sizeof(a))
using namespace std;
//using namespace __gnu_pbds;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-12;
const double PI=acos(-1.0);
const double angcst=PI/180.0;
const ll mod=998244353;
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll qmul(ll a,ll b){ll r=0;while(b){if(b&1)r=(r+a)%mod;b>>=1;a=(a+a)%mod;}return r;}
ll qpow(ll a,ll n){ll r=1;while(n){if(n&1)r=(r*a)%mod;n>>=1;a=(a*a)%mod;}return r;}
ll qpow(ll a,ll n,ll p){ll r=1;while(n){if(n&1)r=(r*a)%p;n>>=1;a=(a*a)%p;}return r;}

int n;
double len[100050];
char str[100050];

void solve()
{
    cin>>n;
    rep(i,1,n)
        cin>>len[i];
    cin>>str+1;
    
    bool isWater=false,isGrass=false;
    double ans=0;
    double flyWater=0,flyGrass=0;
    double tmp;
    rep(i,1,n)
    {
        if(str[i]=='G')
        {
            if(flyWater)
            {
                tmp=min(len[i],flyWater*2);
                flyWater-=tmp/2;
                len[i]-=tmp;
                flyGrass+=tmp;
                ans+=tmp/2*(3-1)+tmp*1;
            }
            ans+=len[i]*3;
            flyGrass+=len[i]/2;
            isGrass=true;
        }
        else if(str[i]=='W')
        {
            ans+=len[i]*2;
            flyWater+=len[i]/2;
            isWater=true;
        }
        else
        {
            if(flyWater)
            {
                tmp=min(len[i],flyWater*2);
                flyWater-=tmp/2;
                len[i]-=tmp;
                ans+=tmp/2*(3-1)+tmp*1;
            }
            if(flyGrass)
            {
                tmp=min(len[i],flyGrass*2);
                flyGrass-=tmp/2;
                len[i]-=tmp;
                ans+=tmp/2*(5-1)+tmp*1;
            }
            if(isWater)
            {
                ans+=len[i]*(3+1);
                len[i]=0;
            }
            if(isGrass)
            {
                ans+=len[i]*(5+1);
                len[i]=0;
            }
        }
        //cerr<<i<<' '<<ans<<'
';
    }
    cout<<(ll)ans<<'
';
}
int main()
{
    closeSync;
    //multiCase
    {
        solve();
    }
    return 0;
}

原文地址:https://www.cnblogs.com/stelayuri/p/13882021.html