POJ_3009_Curling 2.0(DFS+回溯)

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

题意:

要求把一个冰壶从起点“2”用最少的步数移动到终点“3”

其中0为移动区域,1为石头区域,冰壶一旦想着某个方向运动就不会停止,也不会改变方向(想想冰壶在冰上滑动),除非冰壶撞到石头1 或者 到达终点 3。遇到石头后,冰壶会停在石头前面,此时(冰壶静止)才允许冰壶改变方向,而该块石头会破裂。

分析:

1:冰壶并不是走一格算作一步,而是走到石头前面算做一步。

2:这样每走一步,那么石头就会变化,即场地状态就会改变,但是如果改变后找不到最优的,场地还得变回来,即回溯。

3:走的步数超过10输出-1,即剪纸,这也是控制时间所必需的。

 1 /************************************************************************/
 2 /* 
 3 题意:
 4                                                                      */
 5 /************************************************************************/
 6 # include <cstring>
 7 # include <cstdio>
 8 # include <iostream>
 9 using namespace std;
10 const int MAX=25;
11 int n,m,sx,sy,ans;
12 int map[MAX][MAX];
13 int movex[4]={0,0,1,-1},movey[4]={1,-1,0,0};
14 bool isborder(int x,int y) //判断函数
15 {
16     if(x<=0 || x>n || y<=0 || y>m)
17         return true;
18     else
19         return false;
20 }
21 void DFS(int x,int y,int step)
22 {
23     int i,j;
24     if(step>10) //步数超过10直接返回;
25         return ;
26     for(i=0;i<4;i++) //从坐标想,x,y一共可以走四个方向,用数组来模拟。
27                     //分别对四个方向进行查找是否存在找其中的最短路。
28     {
29         int itx=x+movex[i]; //向左(右或者前后)走一步
30         int ity=y+movey[i];
31         if(isborder(itx,ity) || map[itx][ity]==1)
32             continue; //如果这一步出界或者是石头说明不能走,转向另一个方向查找;
33         while(1) //如果这个方向能走,一查到底记录步数;
34         {
35             if(isborder(itx,ity)) //在此过程中出现越界的退出。
36                 break;
37             if(map[itx][ity]==0 || map[itx][ity]==2) //如果是0(冰块),接着往后找
38             {
39                itx+=movex[i];  
40                ity+=movey[i];  
41                continue;  
42             }
43             if(map[itx][ity]==1) //遇到石头截止,并且石头改成冰块,步数加1接着调用函数。
44             {
45                 map[itx][ity]=0;
46                 DFS(itx-movex[i],ity-movey[i],step+1);   
47                 map[itx][ity]=1; //回溯还原为原来的状态,接着朝另一个方向搜索,取他们的最短路径。
48                 break;
49             }
50             if(map[itx][ity] == 3) //再查的过程中遇到出口,直接返回输出。
51             {
52                 if(ans > step+1)
53                     ans=step+1; //加1的原因是走出口这一步也算一步。
54                 return ;
55             }
56 
57         }
58     }
59 }
60 int main()
61 {
62     int i,j;
63     while(scanf("%d%d",&m,&n) != EOF)
64     {
65         if(m==0 && n==0)
66             break;
67         ans=11;     //初始化11步;最大
68         memset(map,1,sizeof(map));
69         for(i=1;i<=n;i++)
70             for(j=1;j<=m;j++)
71             {
72                 scanf("%d",&map[i][j]);
73                 if(map[i][j] == 2) //记录起点的坐标;
74                 {
75                     sx=i;
76                     sy=j;
77                 }
78             }
79             DFS(sx,sy,0); //从起点开始搜索;
80         if(ans <= 10) //如果超过10输出-1;
81             printf("%d\n",ans);
82         else 
83             printf("-1\n");
84     }
85     return 0;
86 }

 

 

posted on 2013-08-26 16:05  随风浪子的博客  阅读(105)  评论(0)    收藏  举报

导航