zoukankan      html  css  js  c++  java
  • 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;
    }
    

  • 相关阅读:
    如何把项目中经常使用的信息放在全局的对象里,随取随用?
    优秀代码
    gcc编译C代码后,输出乱码
    mybatis !=null的一个坑
    String转int[]
    插值算法的公式 mid=low+(key-a[low])/(a[high]-a[low])*(high-low) 是怎么来的
    关于Leetcode的交替打印FooBar,我的答案一直超时
    git找回前几个版本删除的某个文件
    Google 此手机号无法用于验证 解决方法
    Postgresql 一对多如何将原本用,隔开的id替换为name
  • 原文地址:https://www.cnblogs.com/stelayuri/p/13882021.html
Copyright © 2011-2022 走看看