Problem 117: 死亡洞穴
Time Limit:1 Ms| Memory Limit:64 MB
Difficulty:3
Description
在 caima 的 RPG 游戏中,控制着两个人 VV 和 JJ。
这次 VV 和 JJ 掉入了一个死亡洞穴,洞穴是一个 N*M 的矩阵。之所以称之
为死亡洞穴,是因为在这个矩阵中有一些死亡十字。(如下图中的+)
.....
.+++.
.+.+.
V+.J+
由于 VV 和 JJ 被分撒在了两地,而 JJ 还受了重伤,你需要让 VV 赶到 JJ 所
在的地方。为了尽量少的受死亡十字的影响,VV 要尽量远离这些死亡十字。
我们定义洞穴中两个格子(x,y)和(x’,y’)之间的距离为:|x-x'| + |y-y'|
也就是说,我们要使得 VV 再去找 JJ 的路上,离任意死亡十字的距离都尽
可能的远。VV 每次可以往一个格子的上下左右四个方向走一格。
现在你需要写个程序,来计算最好情况下离死亡十字最近的距离。
Input
第一行两个整数 N 和 M,表示矩阵规模。
接下来 N 行 M 列,描述这个洞穴的情况。其中
V 表示 VV 所在的位置;
J 表示 JJ 所在的位置;
. 表示空地;
+ 表示死亡十字。
Output
一行一个数字,表示 VV 在去找 JJ 的路上,最好情况下离死亡十字最近的距离。
Sample Input
4 4
+...
....
....
V..J
Sample Output
3
Hint
数据规模
对于 30% 的数据 N,M<=50。
对于 100% 的数据 N,M<=500。
Source
软件大赛
二分穷举距离时广搜:
Time Limit:1 Ms| Memory Limit:64 MB
Difficulty:3
Description
在 caima 的 RPG 游戏中,控制着两个人 VV 和 JJ。
这次 VV 和 JJ 掉入了一个死亡洞穴,洞穴是一个 N*M 的矩阵。之所以称之
为死亡洞穴,是因为在这个矩阵中有一些死亡十字。(如下图中的+)
.....
.+++.
.+.+.
V+.J+
由于 VV 和 JJ 被分撒在了两地,而 JJ 还受了重伤,你需要让 VV 赶到 JJ 所
在的地方。为了尽量少的受死亡十字的影响,VV 要尽量远离这些死亡十字。
我们定义洞穴中两个格子(x,y)和(x’,y’)之间的距离为:|x-x'| + |y-y'|
也就是说,我们要使得 VV 再去找 JJ 的路上,离任意死亡十字的距离都尽
可能的远。VV 每次可以往一个格子的上下左右四个方向走一格。
现在你需要写个程序,来计算最好情况下离死亡十字最近的距离。
Input
第一行两个整数 N 和 M,表示矩阵规模。
接下来 N 行 M 列,描述这个洞穴的情况。其中
V 表示 VV 所在的位置;
J 表示 JJ 所在的位置;
. 表示空地;
+ 表示死亡十字。
Output
一行一个数字,表示 VV 在去找 JJ 的路上,最好情况下离死亡十字最近的距离。
Sample Input
4 4
+...
....
....
V..J
Sample Output
3
Hint
数据规模
对于 30% 的数据 N,M<=50。
对于 100% 的数据 N,M<=500。
Source
软件大赛
思路:首先要预处理,初始化每个点到十字的最短距离,用作map,方法是广搜,遍历一下输入的整张图,遇到十字就进队列,然后作为开始广搜,搜到队列为空时,就实现了所有十字同步向外扩散,遍历一遍数组即全都初始化为距离十字的最小值。然后思路是从距离的大到小枚举,遇到最大的可以连通的就是答案,每次枚举一个距离,走大于等于这个距离的点。但是为了减少搜索次数,用二分的思想。深搜广搜都可以。另外,距离最大不会超过起点到十字的距离,因为若大于,起点都不能走。故二分的左边界是0,右边界是起点到十字的距离。
二分穷举距离时深搜:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
typedef struct{
int r, c;
int step;
}node;
int ans, flag, mid, s_x, s_y, e_x, e_y;
int n, m, map[505][505], vis[505][505];
int dir[4][4] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
char temp[505][505];
void init();
void init_bfs(int i, int j);
void dfs(int r, int c);
int main(){
int i, j, r, l;
int Max, Min;
scanf("%d %d", &n, &m);
for(i = 0; i < n; i++)
scanf("%s", temp[i]);
init();
ans = 0;
l = 0;
r = map[s_x][s_y];
while(l <= r){
mid = (l + r) / 2;
memset(vis, 0, sizeof(vis));
flag = 0;
dfs(s_x, s_y);
if(flag){
if(ans < mid)
ans = mid;
l = mid + 1;
}
else
r = mid - 1;
}
printf("%d\n", ans);
return 0;
}
void dfs(int r, int c){
if(r < 0 || r >= n || c < 0 || c >= m || vis[r][c] || map[r][c] < mid)
return ;
if(r == e_x && c == e_y){
flag = 1;
return ;
}
vis[r][c] = 1;
dfs(r - 1, c);
dfs(r + 1, c);
dfs(r, c - 1);
dfs(r, c + 1);
}
void init(){
int i, j, k, row, col;
node p, q;
queue <node> Q;
memset(vis, 0, sizeof(vis));
for(i = 0; i < n; i++){
for(j = 0; j < m; j++){
if(temp[i][j] == '+'){
map[i][j] = 0;
p.r = i;
p.c = j;
p.step = 0;
vis[i][j] = 1;
Q.push(p);
}
if(temp[i][j] == 'V'){
s_x = i;
s_y = j;
}
if(temp[i][j] == 'J'){
e_x = i;
e_y = j;
}
}
}
while(!Q.empty()){
q = Q.front();
Q.pop();
for(k = 0; k < 4; k++){
row = q.r + dir[k][0];
col = q.c + dir[k][1];
if(row >= 0 && row < n && col >= 0 && col < m && !vis[row][col]){
vis[row][col] = 1;
p.r = row;
p.c = col;
p.step = q.step + 1;
map[row][col] = p.step;
Q.push(p);
}
}
}
}
二分穷举距离时广搜:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
typedef struct{
int r, c;
int step;
}node;
int ans, flag, s_x, s_y, e_x, e_y;
int n, m, map[505][505], vis[505][505];
int dir[4][4] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
char temp[505][505];
void init();
void init_bfs(int i, int j);
void bfs(int mid);
int main(){
int i, j, r, l, mid;
int Max, Min;
scanf("%d %d", &n, &m);
for(i = 0; i < n; i++)
scanf("%s", temp[i]);
for(i = 0; i < n; i++){
for(j = 0; j < m; j++){
map[i][j] = 65535;
}
}
init();
ans = 0;
l = 0;
r = map[s_x][s_y];
while(l <= r){
mid = (l + r) / 2;
memset(vis, 0, sizeof(vis));
flag = 0;
bfs(mid);
if(flag){
if(ans < mid)
ans = mid;
l = mid + 1;
}
else
r = mid - 1;
}
printf("%d\n", ans);
return 0;
}
void bfs(int mid){
int i, row, col;
node p, q;
queue <node> Q;
p.r = s_x;
p.c = s_y;
vis[p.r][p.c] = 1;
Q.push(p);
while(!Q.empty()){
q = Q.front();
Q.pop();
if(q.r == e_x && q.c == e_y){
flag = 1;
return ;
}
for(i = 0; i < 4; i++){
row = q.r + dir[i][0];
col = q.c + dir[i][1];
if(row >= 0 && row < n && col >= 0 && col < m && !vis[row][col] && map[row][col] >= mid){
vis[row][col] = 1;
p.r = row;
p.c = col;
Q.push(p);
}
}
}
}
void init(){
int i, j, k, row, col;
node p, q;
queue <node> Q;
memset(vis, 0, sizeof(vis));
for(i = 0; i < n; i++){
for(j = 0; j < m; j++){
if(temp[i][j] == '+'){
map[i][j] = 0;
p.r = i;
p.c = j;
p.step = 0;
vis[i][j] = 1;
Q.push(p);
}
if(temp[i][j] == 'V'){
s_x = i;
s_y = j;
}
if(temp[i][j] == 'J'){
e_x = i;
e_y = j;
}
}
}
while(!Q.empty()){
q = Q.front();
Q.pop();
for(k = 0; k < 4; k++){
row = q.r + dir[k][0];
col = q.c + dir[k][1];
if(row >= 0 && row < n && col >= 0 && col < m && !vis[row][col]){
vis[row][col] = 1;
p.r = row;
p.c = col;
p.step = q.step + 1;
if(map[row][col] > p.step)
map[row][col] = p.step;
Q.push(p);
}
}
}
}