zoj3267 Treasure Hunt II 模拟+枚举

    N个城市,每个城市有一些金币,现在A,B两个人在同一个起点P,每人每秒可以从城市i移动到城市i+1或者i-1,并且任何时刻两人的距离不能超过M,求时间T内,两人最多能拿到多少金币。按照题意直接模拟就行,思路不难,代码挺蛋疼,好多细节的地方要考虑。考虑到每个城市的钱只能拿一次,那么两人如果往一个方向走是没意义的,所以一开始两人从起点向两侧走,直到距离为M,或者是时间耗尽了,如果时间耗尽,直接输出答案把,否则考虑在剩下的时间中如何去拿剩下的金币,三种情况,左边尽可能拿完再回来拿右边的;右边尽可能拿完再回来拿左边的;左边拿一部分,掉头去右边拿一部分;仔细想想前两种情况是可以归到最后一种情况里的,所以在这里两次枚举,第一次枚举左边到达的点,处理出先向左到达该店,再掉头最远能到右边的位置,拿这个区间的和来更新答案;第二次枚举右边到达的点,处理出先向右到达该点再向左最远能到哪个位置,同样用这个区间和来更新答案。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
typedef long long ll;
using namespace std;
int a[220000];
ll sum[220000];
int n,m,k,p,q,t;

ll find(int l,int r,int t)
{
    ll res=0;
    for (int k=r; k<=n; k++)
    {
        if (t-(k-r)*2<0) break;
        int kl=l-(t-(k-r)*2);
        kl=max(1,kl);
        res=max(res,sum[k]-sum[kl-1]);
    }
    for (int k=l; k>=1; k--)
    {
        if (t-(l-k)*2<0) break;
        int kr=r+(t-(l-k)*2);
        kr=min(kr,n);
        res=max(res,sum[kr]-sum[k-1]);
    }
    return res;
}
int main()
{
//    freopen("in.txt","r",stdin);
    while(~scanf("%d%d",&n,&p))
    {
        memset(a,0,sizeof a);
        for (int i=1; i<=n; i++)
        scanf("%d",&a[i]);

        scanf("%d%d",&m,&t);
        memset(sum,0,sizeof sum);

        for (int i=1; i<=n; i++)
        sum[i]=sum[i-1]+(ll)a[i];

        int p1=p,p2=p;
        int tt=t;

        while(tt>0)
        {
            if (p2-(p1)>=m-1) break;

            if (p2-(p1)<m-1)
            {
                if (p2<n) p2++;
                if (p1>1) p1--;
                if (p1==1 && p2==n) break;
            }
            tt--;
        }


        ll ans=sum[p2]-sum[p1-1];
        if (tt==0)
        {
            ans=sum[p2]-sum[p1-1];
        }
        else
        {
            if (p2-p1==m) ans=find(p1,p2,tt);
            else if (p2-p1==m-1)
            {
                if (p1>1) ans=max(ans,find(p1-1,p2,tt-1));
                if (p2<n) ans=max(ans,find(p1,p2+1,tt-1));

            }
        }
        cout<<ans<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值