【搜索之BFS + 剪枝】杭电 hdu 1175 连连看

来源:互联网 发布:gta5如何淘宝购买 编辑:程序博客网 时间:2024/05/08 08:08


/* THE PROGRAM IS MADE BY PYY *//*----------------------------------------------------------------------------//    Copyright (c) 2012 panyanyany All rights reserved.    URL   : http://acm.hdu.edu.cn/showproblem.php?pid=1175    Name  : 1175 连连看    Date  : Thursday, April 05, 2012    Time Stage : 2 hours    Result:57132392012-04-05 21:14:58Accepted1175296MS25372K3624 BC++pyyTest Data :Review :做了那么多次,终于都AC了……之前一直以为BFS比DFS快,但是看了很多人DFS的效果,居然神奇又吐血地比我快了十倍,达到了30几MS,而且看别人BFS的效果,也是上千MS,反正综合比起来,BFS居然比DFS还慢。后来想到,DFS可以快速深入,而BFS则是向四面八方快速扩展。也就是说,同样是直线的距离,假如以最快的方法,DFS用5s的时间可以到,那么BFS则是这样的,第1s,扩展一步之遥的一个格,第2s,一步之遥的另一个格,第3s,第4s,同理……于是4s之后,DFS已经走出4步远了,BFS还在第一步……接下来时间的差距就会越来越大了。当然这种情况对图的要求比较特别,HDU的图貌似正好就是这样的,反正我优化后的速度都快不了……//----------------------------------------------------------------------------*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#include <vector>#include <algorithm>#include <iostream>#include <queue>using namespace std ;#define MEM(a, v)        memset (a, v, sizeof (a))    // a for address, v for value#define max(x, y)        ((x) > (y) ? (x) : (y))#define min(x, y)        ((x) < (y) ? (x) : (y))#define INF     (0x3f3f3f3f)#define MAXN    (1002)#define DB    /##/#define LL __int64#define _RANGE(a, b, e)((b) <= (a) && (a) < e)#define _IN(nd)(_RANGE((nd).x, 0, m) && _RANGE((nd).y, 0, n))#define _MAP(nd)map[(nd).y][(nd).x]#define _PATH(nd)path[(nd).y][(nd).x]#define _VIS(nd)vis[(nd).y][(nd).x]struct NODE {int x, y, px, py;int step;int corn;};const int dir[4][2] = {0,1, 0,-1, 1,0, -1,0};intn, m;boolvis[MAXN][MAXN];charmap[MAXN][MAXN];NODEbeg, end, path[MAXN][MAXN];void bfs(){int i;queue<NODE>q;NODEt, nt;MEM(path, -1);MEM(vis, 0);beg.step = 0;beg.corn = 0;beg.px = beg.x;beg.py = beg.y;q.push(beg);while (!q.empty()){t = q.front();q.pop();for (i = 0; i < 4; ++i){nt = t;if (t.corn == 2)// 剪枝……几乎没效果{i = 4;if (nt.y > nt.py)++nt.y;else if (nt.y < nt.py)--nt.y;else if (nt.x > nt.px)++nt.x;else if (nt.x < nt.px)--nt.x;}else{nt.y += dir[i][0];nt.x += dir[i][1];}if (!_IN(nt) || ('0' != _MAP(nt) && _MAP(end) != _MAP(nt)))continue;/* 下一条语句是为了处理这种情况3 41 1 1 10 0 0 01 1 1 111 1 3 3防止它这样走: (1,1)->..(省略号表示直线)..->(1,3)->..->(3,3)即是说,即使遇到相同类型的子,只要不是end指定的目标,就只能当成障碍跳过.*/if (_MAP(end) == _MAP(nt) && !(nt.x == end.x && nt.y == end.y))continue;if (nt.y == t.py && nt.x == t.px)// 后退了continue;if (nt.y != t.py && nt.x != t.px)// 转弯{nt.py = t.y;nt.px = t.x;++nt.corn;}else// 没有转弯{nt.py = t.y;nt.px = t.x;}if (nt.corn >= 3 || (_VIS(nt) && nt.corn >= _PATH(nt).corn))continue;// 这里不剪,貌似会超时的DBprintf ("nt:(%d,%d)<--(%d,%d) corn:%d step:%d\n", nt.y, nt.x,\nt.py, nt.px, nt.corn, nt.step);++nt.step;_PATH(nt) = nt;_VIS(nt) = true;if (nt.y == end.y && nt.x == end.x)return ;q.push(nt);}}}int main(){int i, j, q;while (scanf("%d %d", &n, &m), n | m){getchar();for (j = 0; j < n; ++j){for (i = 0; i < m; ++i){scanf("%c", &map[j][i]);getchar();}}scanf("%d", &q);for (i = 0; i < q; ++i){scanf("%d %d %d %d", &beg.y, &beg.x, &end.y, &end.x);--beg.y; --beg.x;--end.y; --end.x;if (!_IN(beg) || !_IN(end) || _MAP(beg) != _MAP(end) || '0' == _MAP(beg)){puts("NO");continue;}if (beg.x == end.x && beg.y == end.y){puts("YES");continue;}bfs();if (0 <= _PATH(end).corn && _PATH(end).corn <= 2)puts("YES");elseprintf ("NO\n");}}return 0;}