• 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("
    ");
    143         printf("CASE #%d:
    ",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
    ");
    152                 break;
    153             case 1:
    154                 printf("L
    ");
    155                 break;
    156             case 2:
    157                 printf("R
    ");
    158                 break;
    159             case 3:
    160                 printf("D
    ");
    161                 break;
    162             }
    163             deq.pop_front();
    164         }
    165     }
    166     return 0;
    167 }
  • 相关阅读:
    tcp/ip 调优示例
    【ASP.NET】IHttpHandler和IHttpModule
    【.NET框架】Dapper ORM 用法—Net下无敌的ORM
    【JavaScript】setinterval和setTimeout的区别
    【javascript】基于javascript的小时钟
    【ASP.NET】必须知道的ASP.NET核心处理
    【ASP.NET MVC】 路由机制:命名路由
    【ASP.NET MVC】提高页面加载速度:脚本优化
    SMTP协议--在cmd下利用命令行发送邮件
    【ASP.NET MVC】HTML5+MVC上传文件显示进度
  • 原文地址:https://www.cnblogs.com/yongqiang/p/5690178.html
Copyright © 2020-2023  润新知