題目鏈接:
題目
有一個外星人控制了你的大腦。一開始你處於原點。外星人有一個由組成的長度爲的操作序列,分別代表(右,上,下,左)。
平面上有個關鍵點,每當外星人給出一個操作,你需要在這個方向上找到最近的一個關鍵點,並走到那個點上。保證輸入數據合法。
上圖爲第三個樣例的圖示。
輸入
第一行兩個整數 , 。
接下來行,每行兩個整數 , ,代表第個點的座標。
接下來一行,一個長度爲的字符串,代表操作序列。
輸出
一行兩個整數,代表最終你所處的位置。
樣例輸入1
4 4
1 1
1 0
0 1
0 0
RULD
樣例輸出1
0 0
樣例輸入2
7 5
0 0
0 1
0 -1
1 0
1 -1
3 0
3 -1
DRRUD
樣例輸出2
3 -1
樣例輸入3
10 6
0 0
1 1
2 1
0 2
-1 2
-1 3
2 3
2 4
4 3
2 -1
ULURDL
樣例輸出
1 1
數據範圍
的數據,,。
的數據, , 。
思路
這道題我們模擬, 但是要用二分優化。
我們將座標的每一行和每一列所包含的座標點從小到大排序,然後要移動的時候,就用二分來找下一個座標是在哪裏。
(由於座標有負數,我就直接先把所有點的,座標都加上,然後輸出答案的時候再減回去)
還有一點要注意的,就是人在向左移動和向下移動的時候,我們二分要先找到原來的點的位置,再往前挪一個。這樣得到的新的點就是我們要的那個點了。
代碼
#include<vector>
#include<cstdio>
#include<algorithm>
#define addnum 200001
using namespace std;
int n, m, x, y, nx = addnum, ny = addnum;
vector<int>a[addnum << 1];
vector<int>b[addnum << 1];
int main() {
// freopen("tratincice.in", "r", stdin);
// freopen("tratincice.out", "w", stdout);
scanf("%d %d", &n, &m);//讀入
for (int i = 1; i <= n; i++) {
scanf("%d %d", &x, &y);//讀入
x += addnum;//使所有的座標都是正數
y += addnum;
a[x].push_back(y);
b[y].push_back(x);
}
for (int i = 1; i < addnum << 1; i++) {
if (!a[i].empty())
sort(a[i].begin(), a[i].end());//將行排序
if (!b[i].empty())
sort(b[i].begin(), b[i].end());//將列排序
}
for (int i = 1; i <= m; i++) {
char c = getchar();
while (c != 'R' && c != 'L' && c != 'D' && c != 'U') c = getchar();
if (c == 'R') {//向右
int l = 0, r = b[ny].size() - 1;
while (l < r) {
int mid = (l + r) >> 1;
if (b[ny][mid] <= nx) l = mid + 1;
else r = mid;
}
nx = b[ny][l];
}
else if (c == 'L') {//向左
int l = 0, r = b[ny].size() - 1;
while (l < r) {
int mid = (l + r) >> 1;
if (b[ny][mid] < nx) l = mid + 1;
else r = mid;
}
while (b[ny][l] == nx) l--;
nx = b[ny][l];
}
else if (c == 'D') {//向下
int l = 0, r = a[nx].size() - 1;
while (l < r) {
int mid = (l + r) >> 1;
if (a[nx][mid] < ny) l = mid + 1;
else r = mid;
}
while (a[nx][l] == ny) l--;
ny = a[nx][l];
}
else {//向上
int l = 0, r = a[nx].size() - 1;
while (l < r) {
int mid = (l + r) >> 1;
if (a[nx][mid] <= ny) l = mid + 1;
else r = mid;
}
ny = a[nx][l];
}
}
printf("%d %d", nx - addnum, ny - addnum);//輸出(記得減200001)
// fclose(stdin);
// fclose(stdout);
return 0;
}