hihoCoder_推箱子

一.题目

题目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;
}



四.体会

    这道题全在考虑边界条件和写代码速度上面了,并没有太多需要思考的算法问题。



版权所有,欢迎转载,转载请注明出处,谢谢微笑





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
´问题描述: 码头仓库是划分为n×m个格子的矩形阵列。有公共边的格子是相邻格子。当前仓库中 有的格子是空闲的;有的格子则已经堆放了沉重的货物。由于堆放的货物很重,单凭仓库管 理员的力量是无法移动的。仓库管理员有一项任务,要将一个小箱子推到指定的格子上去。 管理员可以在仓库中移动,但不能跨过已经堆放了货物的格子。管理员站在与箱子相对的空 闲格子上时,可以做一次推动,把箱子推到另一相邻的空闲格子。推箱时只能向管理员的对 面方向推。由于要推动的箱子很重,仓库管理员想尽量减少推箱子的次数。 ´编程任务: 对于给定的仓库布局,以及仓库管理员在仓库中的位置和箱子的开始位置和目标位置, 设计一个解推箱子问题的分支限界法, 计算出仓库管理员将箱子从开始位置推到目标位置所 需的最少推动次数。 ´数据输入: 由文件input.txt提供输入数据。输入文件第 1 行有 2个正整数 n和 m(1<=n,m<=100) , 表示仓库是n×m个格子的矩形阵列。接下来有 n行,每行有 m个字符,表示格子的状态。 S 表示格子上放了不可移动的沉重货物; w 表示格子空闲; M 表示仓库管理员的初始位置; P 表示箱子的初始位置; K 表示箱子的目标位置。 ´结果输出: 将计算出的最少推动次数输出到文件 output.txt。如果仓库管理员无法将箱子从开始位 置推到目标位置则输出“No solution!” 。 输入文件示例 输出文件示例 input.txt output.txt

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值