死亡洞穴

来源:互联网 发布:java工资待遇 编辑:程序博客网 时间:2024/04/28 10:49
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
软件大赛


思路:首先要预处理,初始化每个点到十字的最短距离,用作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);            }        }    }}


0 0
原创粉丝点击