一.题目
题目1 : 推箱子
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
-
描述
推箱子是一款经典游戏。如图所示,灰色格子代表不能通过区域,蓝色方格是箱子,黑色圆形代表玩家,含有圆点的格子代表目标点。
规定以下规则:
1、一局游戏中只会有一个箱子,一个玩家和一个目标点。
2、通过方向键控制玩家移动。
3、图中的灰色格子代表墙壁,玩家与箱子都不能通过。
4、推到墙壁的箱子,就无法再将箱子推离墙壁,因为玩家无法到达箱子靠墙壁的一侧去推箱子。也就是说箱子只能以“被推”的方式被移动,不是以“被拉”的方式被移动。但如果玩家将箱子推至墙壁后,垂直墙壁的两侧没有阻碍物,则玩家可以朝这两个不同的方向推移箱子。如果箱子进入角落,就没有办法再推动这个箱子了。
5、玩家是不能走出场景的。玩家推着箱子到达场景边缘,如果继续点击使玩家和箱子向墙壁前进的方向键,箱子和人都会保持不动。玩家的前进方向上如果有墙壁,也是不能前进的。但是这些点击都视为合理的输入。
6、箱子一旦到达目标点,就不能再移动了。但这时,玩家仍然可以在场景内自由行动。如果继续尝试推箱子,那么玩家将会和箱子一起保持在原地不动。
现在,给出一种方向键的点击方案,请判断,这种方案是否能使箱子最终停在目标点上。为了方便表示,我们以0代表空白格子,以4代表不能通过区域,以1代表玩家,以3代表箱子,以2代表目标点。
输入
第一行数据包含三个整数,N,M,S。其中,N(0 < N <= 100)代表格子的宽度,M(0 < M <= 100)代表格子的高度,S(0 < S <= 200)代表测试点的个数。
接下来的M行,每行都会有N个字符,描述当前的盘面。
接下来的S行,每行都代表一个测试点。每行都以一个整数T(0 < T <= 10000)开头,接下来是一个空格和T个字符。这T个字符仅由d,u,l,r这四个字母组成,分别代表了敲击向下,向上,向左,向右的方向键。
输出
对于每个测试点,输出最后箱子是否在目标点上。如果是,输出YES,如果不是,则输出NO。
- 样例输入
-
5 4 3 00000 13000 00200 00000 4 rurd 6 urdldr 6 rrrurd
- 样例输出
-
YES YES NO
二.解题技巧
这道题主要就是考虑各种边界条件的问题,并没有包含过多的算法。
三.实现代码
#include <iostream> #include <vector> using namespace std; class Box { private: vector<vector<char> > Board; unsigned char Width; unsigned char Height; unsigned char X; unsigned char Y; bool IsSucceed; public: // constructor Box(int N, int M); Box(const Box& Origin); void BuildBoard(); void MoveUp(); void MoveDown(); void MoveLeft(); void MoveRight(); void Move(const char& SingleMove); bool Move(const vector<char> &Moves); void Print(); }; Box::Box(int N, int M) : Board(), Width(N), Height(M), X(255), Y(255), IsSucceed(false) { } Box::Box(const Box& Origin):Board(Origin.Board), Width(Origin.Width), Height(Origin.Height), X(Origin.X), Y(Origin.Y), IsSucceed(Origin.IsSucceed) { } void Box::BuildBoard() { for (int IndexOfRows = 0; IndexOfRows < Height; IndexOfRows++) { vector<char> Row; for (int IndexOfCols = 0; IndexOfCols < Width; IndexOfCols++) { char InputChar = 0; cin >> InputChar; InputChar = InputChar - '0'; if (InputChar == 1) { X = IndexOfCols; Y = IndexOfRows; } Row.push_back(InputChar); } Board.push_back(Row); } } void Box::MoveUp() { if (Y < 1) { return; } int NextY = Y - 1; // The upper is the box in the right point if (Board[NextY][X] == 5) { IsSucceed = true; return; } // The upper is box if (Board[NextY][X] == 3 ) { if (Y == 1) { return; } // the upper of the box is the wall if (Board[NextY - 1][X] == 4) { return; } // updating Board[NextY - 1][X] += 3; Board[NextY][X] = 1; if (Board[Y][X] != 2) { Board[Y][X] = 0; } Y = NextY; if (Board[NextY - 1][X] == 5) { IsSucceed = true; } return; } // the upper is wall if (Board[NextY][X] == 4) { return; } // the upper is zero if (Board[NextY][X] == 0) { if (Board[Y][X] != 2) { Board[Y][X] = 0; } Board[NextY][X] = 1; Y = NextY; return; } if (Board[NextY][X] == 2) { Board[Y][X] = 0; Y = NextY; return; } } void Box::MoveDown() { if (Y > (Height - 2)) { return; } int NextY = Y + 1; // The upper is the box in the right point if (Board[NextY][X] == 5) { IsSucceed = true; return; } // The upper is box if (Board[NextY][X] == 3 ) { if (Y == (Height - 2)) { return; } // the upper of the box is the wall if (Board[NextY + 1][X] == 4) { return; } // updating Board[NextY + 1][X] += 3; Board[NextY][X] = 1; if (Board[Y][X] != 2) { Board[Y][X] = 0; } Y = NextY; if (Board[NextY + 1][X] == 5) { IsSucceed = true; } return; } // the upper is wall if (Board[NextY][X] == 4) { return; } // the upper is zero if (Board[NextY][X] == 0) { if (Board[Y][X] != 2) { Board[Y][X] = 0; } Board[NextY][X] = 1; Y = NextY; return; } if (Board[NextY][X] == 2) { Board[Y][X] = 0; Y = NextY; return; } } void Box::MoveLeft() { if (X < 1) { return; } int NextX = X - 1; // The upper is the box in the right point if (Board[Y][NextX] == 5) { IsSucceed = true; return; } // The upper is box if (Board[Y][NextX] == 3 ) { if (X == 1) { return; } // the upper of the box is the wall if (Board[Y][NextX - 1] == 4) { return; } // updating Board[Y][NextX - 1] += 3; Board[Y][NextX] = 1; if (Board[Y][X] != 2) { Board[Y][X] = 0; } X = NextX; if (Board[Y][NextX - 1] == 5) { IsSucceed = true; } return; } // the upper is wall if (Board[Y][NextX] == 4) { return; } // the upper is zero if (Board[Y][NextX] == 0) { if (Board[Y][X] != 2) { Board[Y][X] = 0; } Board[Y][NextX] = 1; X = NextX; return; } if (Board[Y][NextX] == 2) { Board[Y][X] = 0; X = NextX; return; } } void Box::MoveRight() { if (X > (Width - 2)) { return; } int NextX = X + 1; // The upper is the box in the right point if (Board[Y][NextX] == 5) { IsSucceed = true; return; } // The upper is box if (Board[Y][NextX] == 3 ) { if (X == (Width - 2)) { return; } // the upper of the box is the wall if (Board[Y][NextX + 1] == 4) { return; } // updating Board[Y][NextX + 1] += 3; Board[Y][NextX] = 1; if (Board[Y][X] != 2) { Board[Y][X] = 0; } X = NextX; if (Board[Y][NextX + 1] == 5) { IsSucceed = true; } return; } // the upper is wall if (Board[Y][NextX] == 4) { return; } // the upper is zero if (Board[Y][NextX] == 0) { if (Board[Y][X] != 2) { Board[Y][X] = 0; } Board[Y][NextX] = 1; X = NextX; return; } if (Board[Y][NextX] == 2) { Board[Y][X] = 0; X = NextX; return; } } void Box::Move(const char &SingleMove) { //Print(); switch(SingleMove) { case 'u': MoveUp(); break; case 'd': MoveDown(); break; case 'l': MoveLeft(); break; case 'r': MoveRight(); break; default: break; } //cout << "X is " << X << endl; //cout << "Y is " << Y << endl; //Print(); } bool Box::Move(const vector<char> &Moves) { const int SIZE = Moves.size(); for (int Index = 0; Index < SIZE; Index++) { Move(Moves[Index]); if (IsSucceed) { return true; } } return false; } void Box::Print() { const int SIZE = Board.size(); for (int RowIndex = 0; RowIndex < SIZE; RowIndex++) { vector<char> Row = Board[RowIndex]; int COLS = Row.size(); for (int ColIndex = 0; ColIndex < COLS; ColIndex++) { char Tmp = Row[ColIndex] + '0'; cout << Tmp; } cout << endl; } } int main() { int N = 0, M = 0; int S = 0; cin >> N >> M >> S; Box Box_1(N, M); Box_1.BuildBoard(); while (S--) { Box Box_Tmp(Box_1); int Number = 0; vector<char> Moves; cin >> Number; while(Number--) { char SinlgeMove = '0'; cin >> SinlgeMove; Moves.push_back(SinlgeMove); } if (Box_Tmp.Move(Moves)) { cout << "YES" << endl; } else { cout << "NO" << endl; } } return 0; }
四.体会
这道题全在考虑边界条件和写代码速度上面了,并没有太多需要思考的算法问题。
版权所有,欢迎转载,转载请注明出处,谢谢