hdu 1175 连连看

题目中需要注意的地方:

1、转弯次数不能超过两次

2、只有起点位置和终点位置的棋子相同的时候,才进行dfs搜索,否则直接输出"NO"。如果不这样做,会超时!

 

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 typedef struct Node
  6 {
  7     int x1, y1;
  8     int x2, y2;
  9 }Node;
 10 
 11 const int N = 1010;
 12 const int dir[4][2] = { {-1,0}, {0,1}, {1,0}, {0,-1} };
 13 Node inquire[50];    //保存询问信息
 14 bool visit[N][N];    //标记数组
 15 int board[N][N];     //棋盘
 16 int n, m, q;         //行、列、询问次数
 17 
 18 /* 输入(参数含义:行、列) */
 19 void input(void)
 20 {
 21     for (int i = 1; i <= n; ++i)
 22         for (int j = 1; j <= m; ++j)
 23             scanf("%d", &board[i][j]);
 24     scanf("%d", &q);
 25     for (int i = 0; i < q; ++i)
 26         scanf("%d %d %d %d", &inquire[i].x1, &inquire[i].y1, &inquire[i].x2, &inquire[i].y2);
 27 }
 28 
 29 /* 判断是否越界 */
 30 inline bool inBoard(const int &row, const int &col)
 31 {
 32     return 1 <= row && row <= n && 1 <= col && col <= m;
 33 }
 34 
 35 /* dfs搜索(参数含义:行、列、第几次询问、当前的方向、当前的转弯次数) */
 36 bool dfs(const int &row, const int &col, const int &index, int direction ,int turnCount)
 37 {
 38     if (-1 != direction && 0 < board[row][col])// "1 != direction"的目的是防止起点的棋子进来
 39     {
 40         if (inquire[index].x2 == row && inquire[index].y2 == col)
 41             return true;  //碰到一个棋子,棋子能匹配,找到答案
 42         else
 43             return false; //碰到一个棋子,但是这个棋子不能匹配,因此需要退回去,不能继续向下搜索
 44     }
 45 
 46     for (int i = 0; i < 4; ++i)
 47     {
 48         int r = row + dir[i][0];
 49         int c = col + dir[i][1];
 50         if (true == inBoard(r, c) && false == visit[r][c])
 51         {
 52             //记录之前的方向和转弯次数,用于后面回溯
 53             int lastDirection = direction;
 54             int lastTurnCount = turnCount;
 55 
 56             //处理转弯
 57             if (-1 == direction) //方向为-1表示刚开始搜索,还没有选方向
 58             {
 59                 direction = i;
 60             }
 61             else if ( i != direction)  //之前的方向与当前的方向不同,表示一次转弯
 62             {
 63                 if (turnCount + 1 > 2) //转弯次数不能超过两次
 64                     continue;
 65                 direction = i;
 66                 turnCount++;
 67             }
 68 
 69             visit[r][c] = true;
 70 
 71             //搜索
 72             if (true == dfs(r, c, index, direction, turnCount))
 73                 return true;
 74 
 75             //回溯
 76             visit[r][c] = false;
 77             direction = lastDirection;
 78             turnCount = lastTurnCount;
 79         }
 80     }
 81     return false;
 82 }
 83 
 84 int main(void)
 85 {
 86     while (scanf("%d %d", &n, &m), n || m)
 87     {
 88         input();
 89         for (int i = 0; i < q; ++i)
 90         {
 91             if (board[inquire[i].x1][inquire[i].y1] != board[inquire[i].x2][inquire[i].y2])
 92             {
 93                 printf("NO\n");
 94                 continue;
 95             }
 96             memset(visit, 0, sizeof(visit)); //搜索成功了,就不会回溯visit,所以每次开始搜索的时候需要清空visit
 97             visit[inquire[i].x1][inquire[i].y1] = true;
 98             if (true == dfs(inquire[i].x1, inquire[i].y1, i, -1, 0))//-1代表没有方向
 99                 printf("YES\n");
100             else
101                 printf("NO\n");
102         }
103     }
104     return 0;
105 }

 

posted on 2016-07-21 13:17  yqzheng  阅读(138)  评论(0)    收藏  举报

导航