码迷,mamicode.com
首页 > 其他好文 > 详细

hihoCoder_推箱子

时间:2015-04-08 23:25:44      阅读:234      评论:0      收藏:0      [点我收藏+]

标签:c++   algorithm   算法   

一.题目

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



四.体会

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



版权所有,欢迎转载,转载请注明出处,谢谢技术分享

技术分享



hihoCoder_推箱子

标签:c++   algorithm   算法   

原文地址:http://blog.csdn.net/sheng_ai/article/details/44948377

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!