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;
}
标签:sy,sx,前缀,int,4217,len,else,区间,AcWing 来源: https://blog.csdn.net/lymww/article/details/122751510