POJ3009 Curling 2.0

题目链接:

http://poj.org/problem?id=3009

大致题意:

就是要求把一个冰壶从起点“2”用最少的步数移动到终点“3”,其中0为移动区域,1为石头区域,冰壶一旦想着某个方向运动就不会停止,也不会改变方向(想想冰壶在冰上滑动),除非冰壶撞到石头1 或者 到达终点 3。

解题思路:

所谓的“走一步”,就是指冰壶从一个静止状态到下一个静止状态,就是说冰壶在运动时经过的“格数”不视作“步数”,也就是说冰壶每次移动的距离都是不定的。还有就是由于石头会因为冰壶的碰撞而消失,因此冰壶每“走一步”,场地的环境就会改变一次。

AC代码:

#include<iostream>
using namespace std;

typedef class
{
public:
    int x;//冰壶当前的位置
    int y;
    bool status;//false为静止
} chess;

const int inf =11;
chess s, e; //冰壶的起止点
int w, h; //场地的宽和高
int ans;
int board[30][30];

void dfs(int x, int y, bool status, int direction, int step, bool flag)
{
    //direction是指冰壶当前的运动方向:N-0 W-1 S-2 E-3
    //flag:是否消除direction方向下一格位置的石头
    if(step > 10)
        return;
    if(board[x][y] == 3) {
        //终点
        if(ans > step)
            ans = step;
        return;
    }
    if(flag) {
        //消除石头
        switch(direction) {
        case 0: {
            board[x - 1][y] = 0;
            break;
        }
        case 1: {
            board[x][y - 1] = 0;
            break;
        }
        case 2: {
            board[x + 1][y] = 0;
            break;
        }
        case 3: {
            board[x][y + 1] = 0;
            break;
        }
        }
    }
    if(!status) { //静止
        //向北运动
        if(x - 1 >= 1 && (board[x - 1][y] == 0 || board[x - 1][y] == 3))
            dfs(x - 1, y, true, 0, step + 1, false);
        //向西运动
        if(y - 1 >= 1 && (board[x][y - 1] == 0 || board[x][y - 1] == 3))
            dfs(x, y - 1, true, 1, step + 1, false);
        //向南运动
        if(x + 1 <= h && (board[x + 1][y] == 0 || board[x + 1][y] == 3))
            dfs(x + 1, y, true, 2, step + 1, false);
        //向东运动
        if(y + 1 <= w && (board[x][y + 1] == 0 || board[x][y + 1] == 3))
            dfs(x, y - 1, true, 3, step + 1, false);
    } else if(status) {
        switch(direction) {
        case 0: {
            if(x - 1 < 1)
                return ;
            else {
                if(board[x - 1][y] == 0) //下一位置为0且不越界,继续运动
                    dfs(x - 1, y, true, 0, step, false);
                else if(board[x - 1][y] == 1)
                    dfs(x, y, false, 0, step, true); //下一位置为1且不越界,停止运动,并消除下一位置的石头
                else if(board[x - 1][y] == 3)
                    dfs(x - 1, y, false, 0, step, false);
            }
            break;
        }
        case 1: {
            if(y - 1 < 1)
                return ;
            else {
                if(board[x][y - 1] == 0) //下一位置为1且不越界,继续运动
                    dfs(x, y - 1, true, 1, step, false);
                else if(board[x][y - 1] == 1)
                    dfs(x, y, false, 1, step, true); //下一位置为1且不越界,停止运动,并消除下一位置的石头
                else if(board[x][y - 1] == 3)
                    dfs(x, y - 1, false, 1, step, false);
            }
            break;
        }
        case 2: {
            if(x + 1 > h)
                return ;
            else {
                if(board[x + 1][y] == 0) //下一位置为2且不越界,继续运动
                    dfs(x + 1, y, true, 2, step, false);
                else if(board[x + 1][y] == 1)
                    dfs(x, y, false, 2, step, true); //下一位置为1且不越界,停止运动,并消除下一位置的石头
                else if(board[x + 1][y] == 3)
                    dfs(x + 1, y, false, 2, step, false);
            }
            break;
        }
        case 3: {
            if(y + 1 > w)
                return ;
            else {
                if(board[x][y + 1] == 0) //下一位置为3且不越界,继续运动
                    dfs(x, y + 1, true, 3, step, false);
                else if(board[x][y + 1] == 1)
                    dfs(x, y, false, 3, step, true); //下一位置为1且不越界,停止运动,并消除下一位置的石头
                else if(board[x][y + 1] == 3)
                    dfs(x, y + 1, false, 3, step, false);
            }
            break;
        }

        }
    }
    if(flag) { //回溯前还原石头,即还原上一步的棋盘状态
        switch(direction) {
        case 0: {
            board[x - 1][y] = 1;
            break;
        }
        case 1: {
            board[x][y - 1] = 1;
            break;
        }
        case 2: {
            board[x + 1][y] = 1;
            break;
        }
        case 3: {
            board[x][y + 1] = 1;
            break;
        }
        }
    }
    return ;
}


int main()
{
    while(cin >> w >> h)
    {
        if(!w && !h)
            break;
         ans = inf;
        for(int i = 1; i <= h; i++) {
            for(int j = 1; j <= w; j++) {
                cin >> board[i][j];
                if(board[i][j] == 2) {
                    s.x = i;
                    s.y = j;
                    s.status = false;
                    board[i][j] = 0;
                }
                if(board[i][j] == 3) {
                    e.x = i;
                    e.y = j;
                }
            }
        }
        dfs(s.x, s.y, s.status, 0, 0, false);
        if(ans <= 10)
            cout << ans << endl;
        else
            cout << -1 << endl;
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值