杭电OJ_hdu3500_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 }
时间: 2024-10-21 13:57:48

杭电OJ_hdu3500_Fling的相关文章

杭电 HDU 1164 Eddy&#39;s research I

Eddy's research I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7117    Accepted Submission(s): 4268 Problem Description Eddy's interest is very extensive, recently  he is interested in prime

hdu 1016 Prime Ring Problem DFS解法 纪念我在杭电的第一百题

Prime Ring Problem Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 29577    Accepted Submission(s): 13188 Problem Description A ring is compose of n circles as shown in diagram. Put natural num

杭电ACM分类

杭电ACM分类: 1001 整数求和 水题1002 C语言实验题——两个数比较 水题1003 1.2.3.4.5... 简单题1004 渊子赛马 排序+贪心的方法归并1005 Hero In Maze 广度搜索1006 Redraiment猜想 数论:容斥定理1007 童年生活二三事 递推题1008 University 简单hash1009 目标柏林 简单模拟题1010 Rails 模拟题(堆栈)1011 Box of Bricks 简单题1012 IMMEDIATE DECODABILITY

一个人的旅行 HDU杭电2066【dijkstra算法】

http://acm.hdu.edu.cn/showproblem.php?pid=2066 Problem Description 虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,^0^),很多事,还能丰富自己的阅历,还可以看美丽的风景--草儿想去很多地方,她想要去东京铁塔看夜景,去威尼斯看电影,去阳明山上看海芋,去纽约纯粹看雪景,去巴黎喝咖啡写信,去北京探望孟姜女--眼看寒假就快到了,这么一大段时间,可不

杭电1162--Eddy&#39;s picture(Prim()算法)

Eddy's picture Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 8070    Accepted Submission(s): 4084 Problem Description Eddy begins to like painting pictures recently ,he is sure of himself to b

杭电1276--士兵队列训练问题

士兵队列训练问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4605    Accepted Submission(s): 2148 Problem Description 某部队进行新兵队列训练,将新兵从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列,剩下的向小序号方向靠拢,再从头开始进行

杭电1272 并查集找环+判断连通

杭电1272 并查集找环+判断连通 E - E Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 1272 Description 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就是说如果有一个通道连通了房间A和B

杭电ACM Java实现样例

若使用Java求解杭电ACM,答案提交必须注意两点: 1.类名一定得是Main,否则服务器无法编译: 2.必须用while进行输入判断. 以1000题测试题为例,代码如下: import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scan=new Scanner(System.in); while(scan.hasNextInt()) { int a=scan.n

杭电 HDU 1038 Biker&#39;s Trip Odometer

Biker's Trip Odometer Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4745    Accepted Submission(s): 3144 Problem Description Most bicycle speedometers work by using a Hall Effect sensor faste