zoj 1649 Rescue ——BFS入门题
April 8, 2013
zoj
BFS
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=649 题意: 给一个字符矩阵,‘#’代表墙壁,’.‘代表空格,‘x’代表有警察的空格,’r’和’a’分别代表一屌丝,并且’r’要到’a’那里去串门儿,r走一个空格花费单位时间1,走一个有警察的空格需要先干掉警察,话费单位时间1,然后再走过去,也就是共花费时间2,请问屌丝r到屌丝a那里去最少花费的时间。 思路: 首先要搞明白一个问题:就是路径最短的路不一定花费时间最少。这是可以理解的,比如,一条很短但是有很多警察,另一条路很长,但是没有警察,很有可能是第二条路花费时间少。用深搜?貌似不太合适,因为你一条路径访问过一个点后,另一条路径很可能也会访问这个点,并且时间较少。关键是深搜找到的接不一定是最优的。所以,考虑用广搜解。这道题最朴素的广搜显然不行,也就是说,仅仅求步数最少的不可行,需要加上访问时间这个附加条件。 用一个结构体数组存储每个点的信息,包括坐标,到达这个点所需要的最短时间,从起点开始搜,先访问起点,然后把起点出队,如果从一个点A到达下一个点B的当前所需时间比这个点现在标记的时间少,则把这个点入队,然后判断点A的另一个方向上的下一个点。这样,总有一天队列会为空,这是因为,某个点不可能被访问无数次,也就是说,某个点不可能无数次入队,因为到达某个点所需要的时间一定是有个最小值的,所以BFS一定可以结束,并且最后找到的点‘a’的信息一定是最优解。输出就可以了,如果无解,因为初始化到达所有点所需时间都是MAXN,所以,如果点‘a’的时间信息如果等于MAXN,那么说明无解。 第一次做深搜,这道题开始不知道怎么做,看了书上的思路,坚持没看代码,自己又想了想,就试着开始写,好神奇,竟然1A了!!!
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <stack>
#include <queue>
#include <cmath>
#include <algorithm>
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
using namespace std;
typedef long long int LL;
const int MAXN = 0x3f3f3f3f;
const int MINN = -0x3f3f3f3f;
const double eps = 1e-9;
const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1},
{1,1},{1,-1},{-1,-1}};
typedef struct point{
int a, b, t;
}point;
point p[220][220], st, en;
char s[220][220];
int n, m, T, si, sj, di, dj;
queue<point> qt;
void bfs(){
qt.push(st);
while (!qt.empty()){
point po = qt.front();
qt.pop();
for (int k = 0; k < 4; ++k){
int nexti=po.a+dir[k][0],nextj=po.b+dir[k][1];
if (nexti>=0&&nexti<=n&&nextj>=0&&nextj<=m&&s[nexti][nextj]!='#'){
int nowt = po.t+1; if(s[nexti][nextj]=='x') nowt++;
if (nowt<p[nexti][nextj].t){
p[nexti][nextj].t = nowt;
qt.push(p[nexti][nextj]);
}
}
}
}
}
int main(void){
#ifndef ONLINE_JUDGE
freopen("zoj1649.in", "r", stdin);
#endif
while (~scanf("%d%d", &n, &m)){
getchar();
for (int i = 1; i <= n; ++i){
for (int j = 1; j <= m; ++j){
scanf("%c", &s[i][j]);
if (s[i][j] == 'r') {si = i; sj = j;}
else if (s[i][j] == 'a') {di = i; dj = j;}
p[i][j].t = MAXN; p[i][j].a = i; p[i][j].b = j;
} getchar();
}
st.a = si; st.b = sj; st.t = 0;
bfs();
if (p[di][dj].t == MAXN){
printf("Poor ANGEL has to stay in the prison all his life.\n");
} else printf("%d\n", p[di][dj].t);
}
return 0;
}
虽然写的代码还是有点儿挫,但是第一次做就写对了,信心大增,做题好久没有这么爽了! 不过仔细想想,这题确实思路也不难,一次做对是应该的,没什么可得意的……o(╯□╰)o