题目描述:
现在有一队空降兵在执行任务。空降兵一共有 n 名,他们即将一个个空降到战场上。战场已经事先被划分成了 R × C 个方格。在一些方格中,有临时部署好的军事基地。现在给定每个空降兵要降落的位置,请你计算离他降落位置最近的军事基地有多远。我们定义第 i 行第 j 列的方格到第 p 行第 q 列的方格的距离为:(i - p)2 + (j - q)2,即两地之间的欧几里得距离的平方。
输入:
输入第一行,三个整数,n,R 和 C;
接下来 R 行,每行一个长度为 C 的字符串,表示战场的情况,其中. 表示该格方块没有军事基地,o 表示该格方块有军事基地;
接下来 n 行,每行两个整数 x 和 y,表示该名空降兵即将降落在第 x 行第 y 列的方格中。
输出:
输出 n 行,对于每个空降兵,都输出离他降落位置最近的军事基地到他降落位置的距离。
样例输入:
3 4 5
…
.o…
…o
…o…
1 4
2 2
4 5
样例输出:
5
0
1
这题直接暴力的时间复杂度为 O(nRC),会超时,
我们设
表示在第 x 行,在y列的左边,离第y列最近的基地的列号
我们设
表示在第 x 行,在y列的右边,离第y列最近的基地的列号
我们可以先预处理出这两个数组
处理方法:
1:当x, y正好在基地上,
= y,
= y;
2:否则
=
,
=
;
每次询问x, y时,将 到 , 到 所对应的军事基地与x, y的距离的最小值,时间复杂度为O(RC + nR)
代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
int l[1005][1005], r[1005][1005];
int get_dis(int x1, int y1, int x2, int y2){
return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
}
int main(){
int n, R, C, i, j;
scanf("%d%d%d", &n, &R, &C);
char s;
for(i = 1; i <= R; i++){
for(j = 1; j <= C; j++){
cin >> s;
if(s == 'o'){
l[i][j] = j;
r[i][j] = j;
}
}
}
for(i = 1; i <= R; i++){
for(j = 1; j <= C; j++){
if(l[i][j] == 0){
l[i][j] = l[i][j - 1];
}
}
}
for(i = 1; i <= R; i++){
for(j = C; j >= 1; j--){
if(r[i][j] == 0){
r[i][j] = r[i][j + 1];
}
}
}
int x, y, ans;
for(i = 1; i <= n; i++){
scanf("%d%d", &x, &y);
ans = (1 << 30);
for(j = 1; j <= R; j++){
if(l[j][y] != 0)
ans = min(ans, get_dis(j, l[j][y], x, y));
if(r[j][y] != 0)
ans = min(ans, get_dis(j, r[j][y], x, y));
}
printf("%d\n", ans);
}
return 0;
}