题目链接: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了!!!
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cctype> 6 #include <stack> 7 #include <queue> 8 #include <cmath> 9 #include <algorithm> 10 #define lson l, m, rt<<1 11 #define rson m+1, r, rt<<1|1 12 using namespace std; 13 typedef long long int LL; 14 const int MAXN = 0x3f3f3f3f; 15 const int MINN = -0x3f3f3f3f; 16 const double eps = 1e-9; 17 const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1}, 18 {1,1},{1,-1},{-1,-1}}; 19 20 typedef struct point{ 21 int a, b, t; 22 }point; 23 point p[220][220], st, en; 24 char s[220][220]; 25 int n, m, T, si, sj, di, dj; 26 queue<point> qt; 27 void bfs(){ 28 qt.push(st); 29 while (!qt.empty()){ 30 point po = qt.front(); 31 qt.pop(); 32 for (int k = 0; k < 4; ++k){ 33 int nexti=po.a+dir[k][0],nextj=po.b+dir[k][1]; 34 if (nexti>=0&&nexti<=n&&nextj>=0&&nextj<=m&&s[nexti][nextj]!='#'){ 35 int nowt = po.t+1; if(s[nexti][nextj]=='x') nowt++; 36 if (nowt<p[nexti][nextj].t){ 37 p[nexti][nextj].t = nowt; 38 qt.push(p[nexti][nextj]); 39 } 40 } 41 } 42 } 43 } 44 int main(void){ 45 #ifndef ONLINE_JUDGE 46 freopen("zoj1649.in", "r", stdin); 47 #endif 48 while (~scanf("%d%d", &n, &m)){ 49 getchar(); 50 for (int i = 1; i <= n; ++i){ 51 for (int j = 1; j <= m; ++j){ 52 scanf("%c", &s[i][j]); 53 if (s[i][j] == 'r') {si = i; sj = j;} 54 else if (s[i][j] == 'a') {di = i; dj = j;} 55 p[i][j].t = MAXN; p[i][j].a = i; p[i][j].b = j; 56 } getchar(); 57 } 58 st.a = si; st.b = sj; st.t = 0; 59 bfs(); 60 if (p[di][dj].t == MAXN){ 61 printf("Poor ANGEL has to stay in the prison all his life.\n"); 62 } else printf("%d\n", p[di][dj].t); 63 } 64 65 return 0; 66 }
虽然写的代码还是有点儿挫,但是第一次做就写对了,信心大增,做题好久没有这么爽了!
不过仔细想想,这题确实思路也不难,一次做对是应该的,没什么可得意的……o(╯□╰)o