题意:
给一串以‘U’,‘D’,‘L’,‘R’组成的字符串代表一个初始位置为(0,0)的机器人的行走路线。
然后给一个机器人被要求到达的目标位置(e_x,e_y)。
问能够通过修改字符串 l 到 r 区间的任意字符 使得机器人最终能够到达目标位置,求得的最小的 r - l + 1。
题解:
二分答案求得最小的可行解。但是给你一个答案你怎么判断它可行与否呢。
这时可以用前缀和来预处理记录下进行每次移动之后机器人的位置,然后每一次二分时将 l 到 r 这个区间内的所有操作删去,直接判断可不可以通过修改该区间内操作来使得机器人最终到达目标点。具体看代码。
代码:
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#define INF 0x3f3f3f3f
#define MAXM 5 + 10
#define MAXN 200000 + 10
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
int n;
char op[MAXN];
int e_x, e_y;
struct PRE{
int x, y;
}pre[MAXN];
bool deal(int l, int r)
{
int t_x = pre[n].x - (pre[r].x - pre[l-1].x);
int t_y = pre[n].y - (pre[r].y - pre[l-1].y);
int m_x = e_x - t_x;
int m_y = e_y - t_y;
int use = r - l + 1;
use -= abs(m_x) + abs(m_y);
if(use < 0 || use & 1)
return false;
return true;
}
int main()
{
scanf("%d %s %d %d", &n, &op, &e_x, &e_y);
for(int i = 1; i <= n; i ++){
if(op[i-1] == 'L') pre[i].x --;
if(op[i-1] == 'R') pre[i].x ++;
if(op[i-1] == 'U') pre[i].y ++;
if(op[i-1] == 'D') pre[i].y --;
pre[i].x += pre[i-1].x;
pre[i].y += pre[i-1].y;
}
int use = n - (abs(e_x) + abs(e_y));
if(use < 0 || use & 1){
printf("-1\n");
return 0;
}
if(pre[n].x == e_x && pre[n].y == e_y){
printf("0\n");
return 0;
}
int l = 0, r = n;
while(l + 1 < r){
int mid = (l + r) / 2;
int flag = 0;
for(int i = 1; i <= n - mid + 1; i ++){
if(deal(i, i + mid - 1)){
flag = 1;
r = mid;
break;
}
}
if(!flag) l = mid;
}
printf("%d\n", r);
}
/*
The WAM is F**KING interesting .
*/