Vasya and Robot CodeForces - 1073C (经典走方格问题+二分)

题意:机器人从起点(0,0)开始,每次只能向上,下,左,右进行移动,给出一个移动序列,问你通过修改这个移动序列,可以让机器人走到(x,y)点的最小修改量(最小修改量定义为:修改的最大编号-最小编号+1)。

思路:将能否走到(x,y)转化为偏移量能否从 0到 x,0到y.

       我们先模拟一下他给出的移动序列,记录这个序列产生偏移量的前缀和,有了前缀和,我们就可以知道任意区间对结果的偏移量贡献。

下面我们枚举修改长度:它的意思是,我们选取的那个区间,可以随意改动,因为我们只关心这个区间的起点和终点,具体内部如果变化,我们并不关心。

枚举长度使用2分来做,在check()函数里,我们计算出除去这个区间以后,已经走的偏移量,再看这个区间的长度能否满足还需要的偏移量。

还有一个问题是,如果枚举的区间长度大于所需的,那么超出部分一定是偶数,这是走方格问题的一个性质。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+7;
int n;
int sx[maxn],sy[maxn];
int x,y;
bool check(int len)
{
    for(int i=1;i+len<=n+1;i++)
    {
        int tmpx=x,tmpy=y;
        int subx=sx[n]-sx[i+len-1];//最后几步走的,先减回来
        int suby=sy[n]-sy[i+len-1];
        tmpx-=subx;//前面走的
        tmpy-=suby;
        int addx=sx[i-1]-sx[0];//还需要的
        int addy=sy[i-1]-sy[0];
        if(abs(tmpx-addx)+abs(tmpy-addy)<=len&&(len-abs(tmpx-addx)-abs(tmpy-addy))%2==0)
        {
            return 1;
        }
    }
    return false;
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    scanf("%d",&n);
    string s;
    cin>>s;
    scanf("%d%d",&x,&y);
    sx[0]=0,sy[0]=0;
    for(int i=0;i<n;i++)
    {
        if(s[i]=='U')
        {
            sy[i+1]=sy[i]+1;
            sx[i+1]=sx[i];
        }
        else if(s[i]=='D')
        {
            sy[i+1]=sy[i]-1;
            sx[i+1]=sx[i];
        }
        else if(s[i]=='R')
        {
            sx[i+1]=sx[i]+1;
            sy[i+1]=sy[i];
        }
        else if(s[i]=='L')
        {
            sx[i+1]=sx[i]-1;
            sy[i+1]=sy[i];
        }
    }
    int l=0,r=n;
    int ans=-1;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(check(mid))
        {
            r=mid-1;
            ans=mid;
        }
        else
        {
            l=mid+1;
        }
    }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40774175/article/details/83784969