题目传送门
题意:
机器人初始位置在(0,0),然后输入一串指令有R,L,D,U,分别向x,y方向行走,R:x+1,L:x-1,U:y+1,D:y-1;。然后输入目标位置,要你求需要改变的最短区间的长度,使得机器人可以走到目标位置,如果不能则输出-1.
思路:
求最小区间长度,我们可以二分搜索区间长度。
先预处理,求出所有区间的前缀和,二分最短区间的长度。关键设计好check()函数,枚举所有长度为mid的区间,然后通过前缀和计算出所学要改变区间需要对x,y做出的贡献(因为改变的区间的贡献是不定的,所以通过sum-不需要改变区间的贡献)。
AC code:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
typedef long long LL;
int sx[maxn],sy[maxn];
char s[maxn];
int n = 0,x = 0,y = 0;
bool check(int m){
for(int i = 1;i + m -1 <= n;++i){//枚举所有长度为m的区间
int xx = sx[n] - (sx[i+m-1] - sx[i-1]);//不需要改变区间对x,y的贡献值
int yy = sy[n] - (sy[i+m-1] - sy[i-1]);
int tx = x - xx,ty = y - yy;//要改变区间对x,y的贡献值
if(abs(tx) + abs(ty) <= m && (m - (abs(tx) + abs(ty))) % 2 == 0){
return true;
}
}
return false;
}
int main(){
while(~scanf("%d",&n)){
fill(sx,sx+maxn,0);fill(sx,sx+maxn,0);
scanf("%s",s+1);
scanf("%d %d",&x,&y);
for(int i = 1;i <= n;++i){//计算前缀和
sx[i] = sx[i-1] + (s[i] == 'R' ? 1 : (s[i] == 'L' ? -1 : 0));
sy[i] = sy[i-1] + (s[i] == 'U' ? 1 : (s[i] == 'D' ? -1 : 0));
}
int ans = -1,l = 0,r = n;
while(l <= r){//二分搜索区间长度
int mid = (l + r ) >> 1;
if(check(mid)){
ans = mid;
r = mid -1;
}else{
l = mid + 1;
}
}
printf("%d\n",ans);
}
return 0;
}