算法 hdoj 连连看 BFS 木

hdoj 1175 http://acm.hdu.edu.cn/showproblem.php?pid=1175

这题是简单的搜索,给图图中的两个位置,问这两个位置是否可以消去。

有以下情况不能消去:

1,起点和终点有任意一个是非法点,即不是图中的点;

2,起点和终点有任意一个是数值为0的点,即该点事空的。

3,起点和终点的数值不相同。

4,起点和终点的最短距离大于2,这个最短距离是指转弯的次数。

前3点都是直接可以处理的,对于第四点我是采用bfs搜的。记录当前节点的方向和转弯次数即可。

在hdoj c++ 提交 跑了109ms, 弱啊 ! 

View Code
 1 // 用node记录上一次的方向,但是结束条件不是找到终点就返回结果,这样会出错// 
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <queue>
 5 #include <cstring>
 6 #include <algorithm>
 7 using namespace std;
 8 
 9 #define maxn 1088
10 int n, m;
11 int g[maxn][maxn];
12 int step[4][2]={{0,-1}, {0,1},{1,0},{-1,0} };
13 
14 void init(){
15      for ( int i=1; i<=n; ++i )
16        for ( int j=1; j<=m; ++j )
17         scanf ("%d", &g[i][j]);
18 }
19 
20 struct Node{
21     int  x, y;
22     Node(){}
23     Node(int X, int Y):x(X), y(Y){}
24     void scan(){
25         scanf("%d%d", &x, &y);
26     }
27 }s, e;
28 
29 int dist[maxn][maxn];
30 
31 // 判断两个节点是否相等
32 bool is(Node a, Node b){
33    return ( a.x==b.x && a.y==b.y);
34 }
35 // 判断点是否合法
36 bool ok(int x, int y){
37   if(x<1 || y<1 || x>n || y>m) return 0;
38   return 1;
39 }
40 
41 bool bfs(Node a, Node b) {
42     if(!ok(a.x, a.y) || !ok(b.x, b.y)) return 0;
43     if(g[a.x][a.y] != g[b.x][b.y]) return 0;
44     if(!g[a.x][a.y] || !g[b.x][b.y]) return 0;
45     if(is(a, b) ) return 0;
46     
47     for ( int i=1; i<=n; ++i )
48       for ( int j=1; j<=m; ++j )
49       dist[i][j] = 30000;
50 
51     queue<Node > Q;
52     while(!Q.empty() ) Q.pop();
53     Q.push( a );  dist[s.x ][s.y]=0;
54     Q.push( Node(0,0) );
55 
56     while(!Q.empty() ) {
57          Node current = Q.front(); Q.pop();
58          Node last_direct = Q.front(); Q.pop();
59 
60          for ( int i=0; i<4; ++i ){
61              int xx = current.x+ step[i][0];
62              int yy = current.y+ step[i][1];
63              if(!ok(xx, yy) ) continue;
64              //cout <<xx << " " << yy << endl;
65              int d = dist[current.x][current.y];
66              if(!is(last_direct, Node(step[i][0], step[i][1])) ) ++d;
67 
68              if(is(Node(xx, yy), e )  ) { // 节点是终点
69                  dist[xx][yy] = min(dist[xx][yy], d);
70                  if(dist[xx][yy] < 4) return 1;
71              }
72 
73              if(!g[xx][yy] && dist[xx][yy] > d){ 
74               // 入队列的只能是空点,而且是距离更新过的
75                 dist[xx][yy] = d;
76                 if(d > 3) continue;
77                 Q.push(Node(xx, yy) );
78                 Q.push(Node(step[i][0], step[i][1]) );
79              }
80          }
81     }
82     return 0;
83 };
84 
85 void solve(){
86     int q;  scanf("%d", &q);
87     while( q-- ) {
88         s.scan(); e.scan();
89         if( bfs(s, e) ) puts("YES");
90         else puts("NO");
91     }
92 }
93 int main(){
94     while( scanf("%d%d", &n, &m), n||m ){
95         init();
96         solve();
97     }
98 };

 突然想起记录方向时直接用一个数值表示就号可以了,我代码中的记录方法麻烦。。

原文地址:https://www.cnblogs.com/TengXunGuanFangBlog/p/BFS.html