【DFS】POJ-3009 冰壶游戏

题目链接: http://poj.org/problem?id=3009

题目描述:

DFS题,思路简单,可作DFS范版吧~

就是你把一个冰壶球从起点S移动到终点G最少要多少步。

具体规则如下:

1、可以朝水平垂直的四个方向上移动,一旦开始移动,冰壶球就只有遇到砖墙才会停下来,被撞到的砖墙会消失。 

2、中途滑出场外或者移动步骤超过十步就算输。

解题思路: 

说到最短路径,颇有些BFS的意味,而事实上这道题因为有地图的变化,所以BFS很困难,DFS写起来更简单,而且数据量很小不用担心超时。

定义了ans[]数组,存下所有可行方案,再找最短的。

有几小点非常值得注意:

1、超过十步算输。

2、不要被行列数W、H和坐标x、y搞乱。。

3、令墙消失再搜索下一层状态。回来再让墙还原。

4、滑行途中遇到终点即是成功,不用非要站在终点上。

AC代码:

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

typedef struct node
{
    int x;
    int y;
}node;

node start,aim;
int W,H,cc;
int grid[22][22],ans[10000];
int dx[]={-1,0,1,0},
    dy[]={0,1,0,-1};

int ok(int x,int y)
{
    if(x>=0&&x<H&&y>=0&&y<W)//一开始被这里弄混乱了
        return 1;
    return 0;
}

void dfs(node start,int dep)
{
    int i,j,tx,ty;
    if(dep>=10)
        return; //超过十步退出
    else
    {
        tx=start.x;ty=start.y;
        for(i=0;i<4;i++)
        {
            tx=start.x+dx[i];ty=start.y+dy[i];
            if(ok(tx,ty)&&grid[tx][ty]==1)
                {tx=start.x;ty=start.y;continue;}
            tx=start.x;ty=start.y; //这里的目的是判断能不能走这个方向上的第一步,不能就continue
            for(j=0;j<25;j++)
            {
                tx+=dx[i];
                ty+=dy[i];
                if(!ok(tx,ty))break;//出界则break,放弃这一方向
                else if(grid[tx][ty]==3)
                {
                    ans[++cc]=dep+1;
                    break;          //找到终点,用ans记录此种路径的步数,break
                }
                else if(grid[tx][ty]==1)
                {
                    grid[tx][ty]=0;
                    node newstart;
                    newstart.x=tx-dx[i];
                    newstart.y=ty-dy[i];

                    dfs(newstart,dep+1);//墙消失,DFS下一层

                    grid[tx][ty]=1;//墙还原,break
                    break;
                }
            }
        }
    }
    return;
}

void input()
{
    int i,j;
    for(i=0;i<H;i++)
        for(j=0;j<W;j++)
        {
            cin>>grid[i][j];
            if(grid[i][j]==2){start.x=i;start.y=j;}
            else if(grid[i][j]==3){aim.x=i;aim.y=j;}
        }
    //输入检测
/*
    for(i=0;i<H;i++)
    {
        for(j=0;j<W;j++)
            cout<<grid[i][j]<<" ";
        cout<<endl;
    }
    cout<<"起点:"<<start.x<<" "<<start.y<<endl;
    cout<<"终点:"<<aim.x<<" "<<aim.y<<endl;
    cout<<endl;
*/
}

int main()
{
    //freopen("Curling_input.txt","r",stdin);
    //freopen("Curling_output.txt","w",stdout);
    while(scanf("%d%d",&W,&H),W&&H)
    {
        memset(ans,0,sizeof(ans));
        cc=-1;
        input();
        dfs(start,0);
        if(cc==-1)cout<<-1<<endl;   
        else
        {
            int minimum=ans[0];
            for(int i=1;i<=cc;i++)
            {
                if(ans[i]<minimum)minimum=ans[i];
            }
            cout<<minimum<<endl;
        }
    }
    return 0;
}

AC截图:



本题收获:很少做DFS的题~可以说BFS掌握的比DFS好,毕竟那个把队列出来进去就行了,模式很固定。这道题可以说是我过的第一道比较正经的DFS题,几乎用了一天的时间,当然,上午我还在看生成排序的DFS,下午能自己写出这个已经不错了。可以说初步了解了DFS的用法。多次失败调试后,一次提交AC~这是一道涉及地图变化的题,很有意义,至少告诉了我们BFS不是万能的,DFS有其优点。


其它:    这题很好玩的样子。

假期不妨做出一个可玩的游戏,PC/APP待定、

还可以加入一些道具来增加可玩性(比如拾取TNT道具放入道具栏,炸掉身边的墙~)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值