hdu 3500 Fling

题目大意:

  Fling是一款手机益智游戏。

  这个游戏在7*8的棋盘上玩。每一局游戏的棋盘上包含许多毛球。为了获得游戏胜利,你需要从棋盘上移除毛球直到只剩下一个毛球在棋盘上。你把一个毛球扔向另外一个毛球,通过撞击使得另外一个毛球飞出棋盘,用这种方式来完成移除毛球。你可以把毛球向上、下、左、右四个方向扔出去。被扔出去的毛球一旦撞到另一个毛球,就会在另一个毛球前面的格子停下来。同时被撞击的毛球将按照之前的方向向前滚动,直到最后一个被撞击的毛球飞出边界。举个栗子,位于(0, 0)坐标的毛球向右滚动,撞击到位于(0, 5)坐标的毛球,这时撞击的毛球将在(0 ,4)坐标停下来。此外,被撞击的毛球将向右朝前滚动。你不能将一个毛球扔向四个方向中任何一个与它相邻的毛球。然而,一个滚动的毛球在运动的方向撞击与他相邻的毛球这是允许的。

                         

输入:

  输入包含许多组测试用例。

  每一组测试用例 是 7行,每行8个字符来描述的棋盘。‘X’代表一个空格子,‘O’代表一个有毛球的格子。任何一个棋盘中,毛球的数量不会超过12个。每组测试用例之间包含一个空行。

 

输出:

  对于每组测试用例,打印一行格式为“CASE #NUM:”的字符串,NUM的地方为当前测试用例的数量。

  接下来,打印每次扔毛球的记录。每一行包含两个整数X,Y和一个字符Z。(X, Y)表示被选中扔出去的毛球的坐标,最左上角的格子是(0, 0)。Z代表毛球移动的方向:U(上)、L(左)、R(右)、D(下);

  在两个例子之间输出一个空格。

  你可以认为每局都有解。

  如果有许多胜利方案,输出最小的一个。两个序列 A (A1, A2, A3 ... An)和B (B1, B2, B3 ... Bn),假设k是最小的一个使得Ak != Bk成立的数。

  定义:A < B

  (1) Ak中的X < Bk中的X  

  (2) 在Ak中的X = Bk中的X的条件下,Ak中的Y < Bk中的Y

  (3) 在Ak中的(X, Y) = Bk中的(X, Y)的条件下,Ak中的Z < Bk中的Z

  Z的大小按照这个序列:U < L < R < D。

 

这题目需要注意的地方:当一个毛球移动后,会导致其他毛球在棋盘上的位置变化,因此下一次搜索的位置不能从上一次搜索提供的位置开始,不然的话得到的结果就不一定满足题目要求(the smallest one)。如果要得到题目要求的答案,每次搜索都需要扫描棋盘,按照扫描到毛球的先后顺序来进行本次搜索,这样得到的结果才可以满足题目要求。

 

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <deque>
  5 #include <stack>
  6 using namespace std;
  7 
  8 typedef struct Node //记录结果的结点结构
  9 {
 10     int row; //
 11     int col; //
 12     int d;   //方向
 13     Node() {}
 14     Node(int _row, int _col, int _dir) :row(_row), col(_col), d(_dir){}
 15 }Node;
 16 
 17 const int dir[4][2] = { { -1, 0 }, { 0, -1 }, { 0, 1 }, { 1, 0 } }; //方向:上,左,右,下
 18 char board[10][10]; //棋盘
 19 deque<Node> deq;    //记录移动方向
 20 
 21 /* 判断是否越界的函数 */
 22 inline bool inBoard(int row, int col)
 23 {
 24     return 0 <= row && row < 7 && 0 <= col && col < 8;
 25 }
 26 
 27 /* dfs搜索 */
 28 bool dfs(int furball) //furball为剩余毛球的数量
 29 {
 30     if (1 == furball) //当剩余毛球的数量为1的时候,表示游戏胜利
 31         return true;
 32 
 33     /* 由于毛球的碰撞会改变棋盘其他毛球的位置,
 34        如果按照前一个dfs函数提供的开始点来搜索,
 35        往往不能得到题目要求的结果,因此每次都要
 36        扫描一遍棋盘,找到“最小的点”来搜索 */
 37     for (int i = 0; i < 7; ++i)//
 38     {
 39         for (int j = 0; j < 8; ++j)//
 40         {
 41             if ('O' == board[i][j])
 42             {
 43                 for (int k = 0; k < 4; ++k) //方向
 44                 {
 45                     int row = i + dir[k][0];//向前走一步
 46                     int col = j + dir[k][1];
 47                     
 48                     if (false == inBoard(row, col)) continue;
 49                     if ('O' == board[row][col]) continue; //第一步必须是空位置,不然不能向这个方向走
 50                     
 51                     stack<int> recode_row; //recode_row和recode_col用来记录毛球搜索前的的位置,方便后面的回溯
 52                     stack<int> recode_col;
 53 
 54                     
 55 
 56                     //从出发点出发,导致的一系列变化
 57                     while (inBoard(row, col) && 'X' == board[row][col]) //如果是'X'就一直走,直到走出边界或者碰到毛球才停下来
 58                     {
 59                         row += dir[k][0];
 60                         col += dir[k][1];
 61                     }
 62 
 63                     //遇到furball,处理撞击过程(若走出界了还没碰到毛球,说明这个方向不能走)
 64                     if (true == inBoard(row, col) && 'O' == board[row][col])
 65                     {
 66                         //记录本次dfs的出发点
 67                         deq.push_back(Node(i, j, k));
 68 
 69                         //用栈来保存毛球的信息,用于回溯
 70                         recode_row.push(i);
 71                         recode_col.push(j);
 72 
 73                         //记录好了毛球信息后,就可以在棋盘上修改毛球了,
 74                         board[i][j] = 'X';
 75                         board[row - dir[k][0]][col - dir[k][1]] = 'O';
 76                         
 77                         //扔第一个毛球引发的其他毛球移动
 78                         //例如:处理这种情况“XOXOXOOX”,(1,1)向R方向移动,导致其他毛球移动
 79                         while (1)
 80                         {
 81                             recode_row.push(row);
 82                             recode_col.push(col);
 83                             board[row][col] = 'X';
 84                             row += dir[k][0];
 85                             col += dir[k][1];
 86                             while (inBoard(row, col) && 'X' == board[row][col])
 87                             {
 88                                 row += dir[k][0];
 89                                 col += dir[k][1];
 90                             }
 91                             if (true == inBoard(row, col) && 'O' == board[row][col])
 92                                 board[row - dir[k][0]][col - dir[k][1]] = 'O';
 93                             else
 94                                 break;
 95                         }
 96 
 97                         if (dfs(furball - 1)) return true;
 98 
 99                         //回溯
100                         int r, c;
101                         while ( 1 != recode_row.size())
102                         {
103                             r = recode_row.top();
104                             c = recode_col.top();
105                             board[r][c] = 'O';
106                             board[r - dir[k][0]][c - dir[k][1]] = 'X';
107                             recode_row.pop();
108                             recode_col.pop();
109                         }
110                         r = recode_row.top();//与起点相邻的点不需要改成'X'
111                         c = recode_col.top();
112                         board[r][c] = 'O';
113                         deq.pop_back();
114                     }
115                 }
116             }
117         }
118     }
119     return false;
120 }
121 
122 int main(void)
123 {
124     int CASE = 1;
125     int furball = 0;
126     while (scanf("%s", board[0]) != EOF)
127     {
128         furball = 0;
129         for (int i = 1; i < 7; ++i)
130             scanf("%s", board[i]);
131         for (int i = 0; i < 7; ++i)
132             for (int j = 0; j < 8; ++j)
133                 if ('O' == board[i][j])
134                     furball++;//记录毛球的总数
135 
136         //搜索
137         dfs(furball);
138         
139         //输出
140         Node res;
141         if (CASE > 1)
142             printf("\n");
143         printf("CASE #%d:\n",CASE++);
144         while (!deq.empty())
145         {
146             res = deq.front();
147             printf("%d %d ", res.row, res.col);
148             switch (res.d)
149             {
150             case 0:
151                 printf("U\n");
152                 break;
153             case 1:
154                 printf("L\n");
155                 break;
156             case 2:
157                 printf("R\n");
158                 break;
159             case 3:
160                 printf("D\n");
161                 break;
162             }
163             deq.pop_front();
164         }
165     }
166     return 0;
167 }

 

posted on 2016-07-21 00:13  yqzheng  阅读(267)  评论(0编辑  收藏  举报

导航