HDU 1175 连连看(BFS或DFS)

连连看

              Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

                       Total Submission(s): 12814    Accepted Submission(s): 3351

Problem Description
“连连看”相信很多人都玩过。没玩过也没关系,下面我给大家介绍一下游戏规则:在一个棋盘中,放了很多的棋子。如果某两个相同的棋子,可以通过一条线连起来(这条线不能经过其它棋子),而且线的转折次数不超过两次,那么这两个棋子就可以在棋盘上消去。不好意思,由于我以前没有玩过连连看,咨询了同学的意见,连线不能从外面绕过去的,但事实上这是错的。现在已经酿成大祸,就只能将错就错了,连线不能从外围绕过。 玩家鼠标先后点击两块棋子,试图将他们消去,然后游戏的后台判断这两个方格能不能消去。现在你的任务就是写这个后台程序。
 

 

Input
输入数据有多组。每组数据的第一行有两个正整数n,m(0<n<=1000,0<m<1000),分别表示棋盘的行数与列数。在接下来的n行中,每行有m个非负整数描述棋盘的方格分布。0表示这个位置没有棋子,正整数表示棋子的类型。接下来的一行是一个正整数q(0<q<50),表示下面有q次询问。在接下来的q行里,每行有四个正整数x1,y1,x2,y2,表示询问第x1行y1列的棋子与第x2行y2列的棋子能不能消去。n=0,m=0时,输入结束。 注意:询问之间无先后关系,都是针对当前状态的!
 

 

Output
每一组输入数据对应一行输出。如果能消去则输出"YES",不能则输出"NO"。
 

 

Sample Input
3 4
1 2 3 4
0 0 0 0
4 3 2 1
4
1 1 3 4
1 1 2 4
1 1 3 3
2 1 2 4
3 4
0 1 4 3
0 2 4 1
0 0 0 0
2
1 1 2 4
1 3 2 3
0 0
 

 

Sample Output
YES
NO
NO
NO
NO
YES
 
 
 
方法一:用BFS求解
  1 #include <stdio.h>
  2 #include <string.h>
  3 
  4 typedef struct _QUEUE           //定义一个队列,保存相关信息
  5 {
  6     int preX, preY;
  7     int curX, curY;
  8     int turnCount;
  9 }QUEUE;
 10 
 11 int M, N;                       //N代表行,M代表列
 12 int sRow, sCol;                 //起始点
 13 int eRow, eCol;                 //到达的终点
 14 const int MAX_NUM = 1005;
 15 int   maze[MAX_NUM][MAX_NUM];   //记录迷宫
 16 int   step[MAX_NUM][MAX_NUM];   //记录某个点的最小拐弯次数
 17 QUEUE qu[MAX_NUM * MAX_NUM];    //对每个符合条件的点入队列
 18 int   dir[4][2] = {{0,-1}, {0,1}, {-1,0}, {1,0}};
 19 
 20 bool bfs()
 21 {
 22     memset(step, 0x7f, sizeof(step)); //将每个点的最小拐弯次数初始为正无穷
 23     qu[0].preX = qu[0].curX = sRow;   //起点入队列
 24     qu[0].preY = qu[0].curY = sCol;
 25     qu[0].turnCount = 0;
 26 
 27     int front = -1, tail = 0;
 28     while(front < tail)              //队列不空时循环
 29     {
 30         QUEUE tempP = qu[++front];
 31         if(tempP.curX == eRow && tempP.curY == eCol) //找到出口
 32             return true;
 33 
 34         for(int k = 0; k < 4; k++)   //向四个方向拓展
 35         {
 36             QUEUE tempC;
 37             tempC.preX = tempP.curX; //计算下一个点的相关信息
 38             tempC.preY = tempP.curY;
 39             tempC.curX = tempP.curX + dir[k][0];
 40             tempC.curY = tempP.curY + dir[k][1];
 41 
 42             if(tempC.curX > 0 && tempC.curX <= N && tempC.curY > 0 
 43                 && tempC.curY <= M && maze[tempC.curX][tempC.curY] == 0)    
 44             {
 45                 if( (tempP.preX == tempP.curX && tempP.curX == tempC.curX)
 46                     || (tempP.preY == tempP.curY && tempP.curY == tempC.curY) )
 47                 {
 48                     tempC.turnCount = tempP.turnCount;    //在同一条直线
 49                 }
 50                 else
 51                 {
 52                     tempC.turnCount = tempP.turnCount + 1;//不在同一条直线
 53                 }
 54 
 55                    //若拐点小于等于2,且小于step[][],主要是防止将已经走过的点入队列
 56                 if(tempC.turnCount <= 2 && tempC.turnCount < step[tempC.curX][tempC.curY])
 57                 {
 58                     step[tempC.curX][tempC.curY] = tempC.turnCount;
 59                     qu[++tail] = tempC;                  //符合条件的点入队列
 60                 }
 61             }
 62         }
 63     }
 64     return false; //找不到出口,返回false
 65 }
 66 
 67 int main()
 68 {
 69     while(scanf("%d %d", &N, &M) && M+N)
 70     {
 71         for(int row = 1; row <= N; row++)
 72         {
 73             for(int col = 1; col <= M; col++)
 74             {
 75                 scanf("%d", &maze[row][col]);
 76             }
 77         }
 78 
 79         int Q;
 80         scanf("%d", &Q);
 81         while(Q--)
 82         {
 83             scanf("%d %d %d %d", &sRow, &sCol, &eRow, &eCol);
 84 
 85             if(maze[sRow][sCol] == 0 || maze[sRow][sCol] != maze[eRow][eCol]
 86                 || maze[eRow][eCol] == 0 || (sRow == eRow && sCol == eCol))
 87             {
 88                 printf("NO\n");
 89                 continue;
 90             }
 91 
 92             int tempValue = maze[eRow][eCol];//将终点值赋给临时变量
 93             maze[eRow][eCol] = 0;            //将终点位置置为0
 94 
 95             bool bResult = bfs();            //BFS搜索
 96 
 97             if(bResult)
 98                 printf("YES\n");
 99             else
100                 printf("NO\n");
101 
102             maze[eRow][eCol] = tempValue;   //恢复终点位置的值
103         }
104     }
105     return 0;
106 }

 

方法二:DFS求解

 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 int M, N;                           //N代表行,M代表列
 5 int sRow, sCol;                     //起始点
 6 int eRow, eCol;                     //到达的终点
 7 const int MAX_NUM = 1005;
 8 int   maze[MAX_NUM][MAX_NUM];       //记录迷宫
 9 int   visit[MAX_NUM][MAX_NUM];      //记录某个点是否被访问
10 int   dir[4][2] = {{0,-1}, {0,1}, {-1,0}, {1,0}};
11 bool  bResult;                      //记录结果
12 
13 //分别记录前一个点位置,当前点的位置,以及当前点的拐弯次数
14 void dfs(int preX, int preY, int curX, int curY, int turnCount)
15 {
16     if(bResult)return;               //已经找到方案则返回
17     if(turnCount > 2)return;         //当前点的拐弯次数大于2,直接返回
18 
19     if(curX == eRow && curY == eCol) //找到终点,置bResult为true
20     {
21         bResult = true;
22         return ;
23     }
24 
25     for(int k = 0; k < 4; k++)       //向四个方向拓展
26     {
27         int nextX = curX + dir[k][0];
28         int nextY = curY + dir[k][1];
29 
30         if(nextX > 0 && nextX <= N && nextY > 0 && nextY <= M) //在迷宫范围内
31         {
32             if(!visit[nextX][nextY] && maze[nextX][nextY] == 0)//没有访问且值为0
33             {
34                 int nTurn;
35                 if( (preX==curX&&curX==nextX || preY==curY&&curY==nextY) )
36                 {
37                     nTurn = turnCount;       //若在一条线上,拐点数目不增加
38                 }
39                 else
40                 { 
41                     nTurn = turnCount + 1;   //不在同一条线上,拐点次数加一
42                 }
43                 
44                 visit[nextX][nextY] = 1;     //标记为已访问
45                 dfs(curX, curY, nextX, nextY, nTurn);  //搜索下一个点
46                 visit[nextX][nextY] = 0;     //回溯时,恢复原来状态
47             }
48         }
49     }
50 }
51 
52 int main()
53 {
54     while(scanf("%d %d", &N, &M) && M+N)
55     {
56         for(int row = 1; row <= N; row++)
57         {
58             for(int col = 1; col <= M; col++)
59             {
60                 scanf("%d", &maze[row][col]);
61             }
62         }
63 
64         int Q;
65         scanf("%d", &Q);
66         while(Q--)
67         {
68             scanf("%d %d %d %d", &sRow, &sCol, &eRow, &eCol);
69 
70             if(maze[sRow][sCol] == 0 || maze[sRow][sCol] != maze[eRow][eCol] 
71                 || maze[eRow][eCol] == 0 || (sRow == eRow && sCol == eCol))
72             {
73                 printf("NO\n");
74                 continue;
75             }
76 
77             bResult = false;
78             memset(visit, 0, sizeof(visit));
79 
80             int tempValue = maze[eRow][eCol]; //将终点值赋给临时变量
81             maze[eRow][eCol] = 0;             //将终点位置置为0
82 
83             dfs(sRow, sCol, sRow, sCol, 0);   //DFS搜索
84 
85             if(bResult)
86                 printf("YES\n");
87             else
88                 printf("NO\n");
89 
90             maze[eRow][eCol] = tempValue;     //恢复终点位置的值
91         }
92     }
93     return 0;
94 }

 

posted @ 2013-05-28 11:48  Dreamcaihao  阅读(226)  评论(0编辑  收藏  举报