题目链接: 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道具放入道具栏,炸掉身边的墙~)