海淀区第三届“智慧杯”中小学生计算机程序设计大赛编程思维类初赛(初中组) 空降兵

题目描述:

现在有一队空降兵在执行任务。空降兵一共有 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),会超时,
我们设 l [ x ] [ y ] l[x][y] 表示在第 x 行,在y列的左边,离第y列最近的基地的列号
我们设 r [ x ] [ y ] r[x][y] 表示在第 x 行,在y列的右边,离第y列最近的基地的列号

我们可以先预处理出这两个数组
处理方法:
1:当x, y正好在基地上, l [ x ] [ y ] l[x][y] = y, r [ x ] [ y ] r[x][y] = y;
2:否则 l [ x ] [ y ] l[x][y] = l [ x ] [ y 1 ] l[x][y - 1] , r [ x ] [ y ] r[x][y] = r [ x ] [ y + 1 ] r[x][y + 1] ;

每次询问x, y时,将 l [ 1 ] [ y ] l[1][y] l [ R ] [ y ] l[R][y] , r [ 1 ] [ y ] r[1][y] r [ R ] [ y ] r[R][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;
} 

猜你喜欢

转载自blog.csdn.net/linwenqidbk/article/details/102992843