AcWing 4217. 机器人移动(二分+向量前缀和)

机器人移动
题目给的数据范围 1 0 5 10^5 105想想是不是可以用二分来做
要想用二分就要看答案是否满足 两端性 意思就是由答案将整个区间分为两部分,小于答案的不满足,大于答案的满足

这道题可以二分区间的长度len, 用f(len)来判定修改len区间是否可以走到终点 ,这样最终的ans就是最小的满足条件的len

接下来就是f(len)里应该怎么判断是否可以走到终点

枚举所有长度为len的区间,因为所有长度为len的区间我们是可以随意改变里面的值的,所有我们只需要找出来除了这个区间后,当前走到的位置和目标位置相差的距离

这里除了这个区间是可以用前缀和O(1)实现的

最后就是看当前走到的位置(x, y)能否通过改变区间走到目标位置(X,Y)

这里可以用曼哈顿距离来考虑,因为每次移动只能再水平或者竖直的分量增加或者减少,所以 ①|X - x| + |Y - y| >= len
②因为一共要走len步即 ∣ X − x ∣ + ∣ Y − y ∣ − ( d 1 + d 2 + d 3 + . . . + d l e n ) = 0 |X - x| + |Y - y| - (d_1 + d_2 + d_3 + ... + d_{len}) = 0 ∣X−x∣+∣Y−y∣−(d1​+d2​+d3​+...+dlen​)=0
由 a − b = 0 a - b = 0 a−b=0 可得 a = b a = b a=b 即 a 与 b 的奇偶性一定相同
曼哈顿距离与len的奇偶性相同

#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>

using namespace std;

const int N = 2e5 + 10;

int n;
int X, Y;
int sx[N], sy[N]; // 保存坐标前缀和
char str[N]; 

bool f(int len)
{
	for(int i = 1; i <= n - len + 1; i ++)
	{
		int j = i + len - 1;
		int x = sx[n] - (sx[j] - sx[i - 1]);
		int y = sy[n] - (sy[j] - sy[i - 1]);
		int d = abs(x - X) + abs(y - Y);
		if(d <= len && (d - len) % 2 == 0) return true;
	}
	
	return false;
}

int main()
{
    cin >> n;
    scanf("%s", str + 1);
    cin >> X >> Y;
    for(int i = 1; i <= n; i ++) 
    {
    	sx[i] += sx[i - 1]; sy[i] += sy[i - 1];
    	char  c = str[i];
    	if(c == 'U') sy[i] ++;
    	else if(c == 'D') sy[i] --;
    	else if(c == 'L') sx[i] --;
    	else sx[i] ++;
	}
	
	if(abs(X) + abs(Y) > n || (X + Y - n) % 2) puts("-1");
	else 
	{
		int l = 0, r = n;
		while(l < r)
		{
			int mid = l + r >> 1;
			if(f(mid)) r = mid;
			else l = mid + 1;
			
		}
		
		cout << r << endl;
	}
	
	return 0;
}
上一篇:简陋迷宫生成和寻路


下一篇:L1-009 N个数求和