CodeForces 1073C Vasya and Robot
在平面直角坐标系中,一个机器人处于(0,0)点。它能进行以下的移动操作。 U 从(x,y)移动到(x,y+1); D 从(x,y)移动到(x,y-1); L 从(x,y)移动到(x-1,y); R 从(x,y)移动到(x+1,y). 现在有一个长度为n的操作序列。Vasya想修改这个序列使机器人最终移动到(x,y)。其修改的花费为maxID-minID+1。maxID是修改的操作的下标的最大值,minID是修改的操作的下标的最小值。如果没有修改,则花费为0。
Input
第一行一个整数,为n (1≤n≤2×10^5). 第二行一个长度为n的字符串,表示原来的操作序列。 第三行两个整数,为x,y。
Output
共一行,如果最后能够移动到(x,y),输出最小的花费,否则,输出−1。
Examples
5
RURUU
-2 3
3
4
RULR
1 1
0
3
UUU
100 100
-1
Note第一个样例中将序列改成LULUU。
第二个样例中,序列不用改变。
第三个样例中,无论如何修改都无法到达(x,y)
思路:
二分法求长度,
判断修改此长度的串能否达到终点
能的话r-1
不能l+1
具体实现判断过程:
只要横向移动为x,纵向移动为y就能刚好到达终点。很明显如果步数奇偶性和x+y的奇偶性不同的话肯定无法刚好到达终点。
遍历字符串,cx[i],cy[i]为走到i时的横纵移动量,递推建立前缀和数组。先将前一个cx,cy赋值给当前,判断当前字符Up cy+1 Down cy-1 Right cx+1 Left cx-1
然后判断时,将该长度在字符串上从左向右滑动,只计算除这段之外的横纵移动量(用前缀和数组直接查询),然后距离(x,y)的横绝对值+纵绝对值 如果小于等于长度,说明能刚好到达终点。
AC代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 #define ll long long 6 using namespace std; 7 8 const int N = 1e6; 9 char s[N]; 10 int cx[N],cy[N]; 11 int n,x,y; 12 int cost; 13 14 bool isok(int len) 15 { 16 for(int i = 1; i <= n; ++i) 17 { 18 if(i+len-1 > n) return 0; 19 int x0 = cx[i-1]-cx[0], y0 = cy[i-1]-cy[0]; 20 x0 += cx[n]-cx[i+len-1]; 21 y0 += cy[n]-cy[i+len-1]; 22 int temp = abs(x-x0)+abs(y-y0); 23 if(temp <= len) 24 return 1; 25 } 26 return 0; 27 } 28 29 int main() 30 { 31 #ifdef local 32 freopen("in.txt","r",stdin); 33 #endif // local 34 cin >> n >> s >> x >> y; 35 int tmp = abs(x) + abs(y); 36 if(tmp > n || (n&1) != (tmp&1)) 37 puts("-1"); 38 else 39 { 40 for(int i = 1; i <= n; ++i) 41 { 42 cx[i] = cx[i-1]; 43 cy[i] = cy[i-1]; 44 int idx = i-1; 45 if(s[idx] == 'U') cy[i]++; 46 if(s[idx] == 'D') cy[i]--; 47 if(s[idx] == 'L') cx[i]--; 48 if(s[idx] == 'R') cx[i]++; 49 } 50 int l = 0, r = n; 51 int ans = -1; 52 while(l <= r) 53 { 54 int mid = (l+r)/2; 55 if(isok(mid)) 56 { 57 ans = mid; 58 r = mid-1; 59 } 60 else 61 { 62 l = mid+1; 63 } 64 } 65 cout << ans; 66 } 67 return 0; 68 }