题意:机器人从起点(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;
}