poj3009

很有意思的题,注意当碰撞完石头后,回溯要恢复石头,否则下一次再深搜时就WA了 。

要注意题目中说明大于10步就impossible,我们在深搜时应该以此

#include <iostream>
#include <memory.h>
using namespace std;
typedef struct S
{
    int r,c;
    bool status;//true运动false静止
}SE;
SE s,e;
int w,h;
int minstep;
const int inf = 11;
int board[30][30];
void dfs(int i,int j,bool status,int direction,int step,bool flag)
//flag说明下一步是否需要让墙消失
//上左下右 0123
{
    if(step>10)
      return;//剪枝
    if(board[i][j]==3)
     {
         if(step<minstep)
           minstep = step;
        return;
     }
    if(flag)
    {
        switch(direction)
        {
            case 0:{board[i-1][j]=0;break;}
            case 1:{board[i][j-1]=0;break;}
            case 2:{board[i+1][j]=0;break;}
            case 3:{board[i][j+1]=0;break;}
        }


    }
    if(!status)//静止
    {
        if(i-1>=1 && (board[i-1][j]==0 || board[i-1][j]==3))  //North
            dfs(i-1,j,true,0,step+1,false);

        if(j-1>=1 && (board[i][j-1]==0 || board[i][j-1]==3))  //West
            dfs(i,j-1,true,1,step+1,false);

        if(i+1<=h && (board[i+1][j]==0 || board[i+1][j]==3))  //South
            dfs(i+1,j,true,2,step+1,false);

        if(j+1<=w && (board[i][j+1]==0 || board[i][j+1]==3))  //East
            dfs(i,j-1,true,3,step+1,false);
    }
    else if(status)
    {
        switch(direction)
        {
            case 0:
                {
                    if(i-1<1)  //预判下一步是否越界
                        return;
                    else
                    {
                        if(board[i-1][j]==0)          //下一位置为0且不越界,继续运动
                            dfs(i-1,j,true,0,step,false);
                        else if(board[i-1][j]==1)          //下一位置为1且不越界,停止运动,并消除下一位置的石头
                            dfs(i,j,false,0,step,true);
                        else if(board[i-1][j]==3)          //下一位置为3且不越界,运动到位置3后停止运动,游戏结束
                            dfs(i-1,j,false,0,step,false);
                    }

                    break;
                }
            case 1:
                {
                    if(j-1<1)  //预判下一步是否越界
                        return;
                    else
                    {
                        if(board[i][j-1]==0)          //下一位置为0且不越界,继续运动
                            dfs(i,j-1,true,1,step,false);
                        else if(board[i][j-1]==1)          //下一位置为1且不越界,停止运动,并消除下一位置的石头
                            dfs(i,j,false,1,step,true);
                        else if(board[i][j-1]==3)          //下一位置为3且不越界,运动到位置3后停止运动,游戏结束
                            dfs(i,j-1,false,1,step,false);
                    }

                    break;
                }
            case 2:
                {
                    if(i+1>h)  //预判下一步是否越界
                        return;
                    else
                    {
                        if(board[i+1][j]==0)          //下一位置为0且不越界,继续运动
                            dfs(i+1,j,true,2,step,false);
                        else if(board[i+1][j]==1)          //下一位置为1且不越界,停止运动,并消除下一位置的石头
                            dfs(i,j,false,2,step,true);
                        else if(board[i+1][j]==3)          //下一位置为3且不越界,运动到位置3后停止运动,游戏结束
                            dfs(i+1,j,false,2,step,false);
                    }

                    break;
                }
            case 3:
                {
                    if(j+1>w)  //预判下一步是否越界
                        return;
                    else
                    {
                        if(board[i][j+1]==0)          //下一位置为0且不越界,继续运动
                            dfs(i,j+1,true,3,step,false);
                        else if(board[i][j+1]==1)          //下一位置为1且不越界,停止运动,并消除下一位置的石头
                            dfs(i,j,false,3,step,true);
                        else if(board[i][j+1]==3)          //下一位置为3且不越界,运动到位置3后停止运动,游戏结束
                            dfs(i,j+1,false,3,step,false);
                    }

                    break;
                }
        }
    }
    if(flag)//回溯还原石头
    {
        switch(direction)
        {
            case 0: {board[i-1][j]=1; break;}
            case 1: {board[i][j-1]=1; break;}
            case 2: {board[i+1][j]=1; break;}
            case 3: {board[i][j+1]=1; break;}
        }
    }
    return;
}
int main()
{
    while(cin>>w>>h)
    {
        if(!w&&!h)
          break;
        minstep = 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.r = i;
                   s.c = j;
                   s.status = false;
                   board[i][j] = 0;
               }
               if(board[i][j]==3)
               {
                   e.r = i;
                   e.c = j;
               }
           }
           dfs(s.r,s.c,s.status,0,0,false);
           if(minstep<=10)
             cout<<minstep<<endl;
             else
             cout<<-1<<endl;
    }
    return 0;
}

做为剪枝条件,否则必定TLE。

源码:


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值