一.题目
题目1 : 推箱子
-
描述
推箱子是一款经典游戏。如图所示,灰色格子代表不能通过区域,蓝色方格是箱子,黑色圆形代表玩家,含有圆点的格子代表目标点。
规定以下规则:
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;
}