hdoj 1010 迷宫问题--回溯法 dfs也行 判断a是否能到b点

思想1:电脑就是一个有特性(很有耐心)的小孩,作为编程人员应该站在它的角度考虑问题,编程就是用一种特定的编程语言跟它交流。

思想2:站在编程员得角度思考,数学是电脑的神经,数学思维是他的灵魂,数学知识是他的身体,知识是有体系的,他有自己独有的性质、属性、规律,编程人员就是用一种特定的编程语言依据他独有的知识、属性、规律进行有规律的不断的推理,直到到达目标,而这目标和知识以及他的一些性质都是由现实生活中一些实际问题,经过分块简化抽象,数学模型抽象而来。

算法核心:回溯在现实生活中就是一种试探的尝试,例如,你很久以前去过一个地方,只很清楚记得目的地的一个特征(假设到时你能知道),现在你在一个十字路口,不知哪个方向是目的地所在的方向,那就只能选择一个方向进行试探,如果运气不好的话,错了,就只能回到十字路口,在进行下一个方向的尝试,这个回到十字路口就是一种回溯。

算法具体描述:结合迷宫问题分析,

现实问题简化抽象:电脑是一个小孩在这个问题中就是只知道往四个方向(上、下、左、右)走,能够分辨越界,开始,结束,通路,墙壁。能否M步从开始到结束。

数学模型抽象:用S代表开始位置,D代表结束位置,X代表墙壁,‘.’代表通路,i代表行坐标,j就代表列坐标,n(0)代表行坐标的最大值(最小值),m(0)就代表列坐标最大值(最小值),(i+1,j)代表向下走一步,(i,j+1)代表向右走一步,(i-1,j)代表向上走一步,(i,j-1)代表向左走一步,当i>n或j>m或i<0或j<0是代表越界。

编程语言抽象:包括三个方面,

      1,数据结构(知识)。

        一个二维的字符数组s[10][10]代表整个迷宫。s[i+1][j]代表先下走一步,s[i-1][j]代表向上走一步,s[i][j-1]代表向左走一步,s[i][j+1]代表向右走一步。

s[i][j]=S代表起始位置,s[i][j]=D代表结束位置,s[i][j]=X代表墙壁位置,s[i][j]=‘.’代表通路位置,

      2,操作(性质 属性 规律)。

        s[10][10]每次只能向上、下、左、右移动一步。只能从S位置开始,D位置结束。X位置不能经过。

      3,目标。

        判读是否存在s[i][j]从S位置到D位置经过的通路个数是否等于M。

编程实现要点:

      1,标记。经过的位置s[i][j]=X。

      2,剪纸(重点)。

      3,判断结束的标记。

源代码:

1 #include < iostream >
2 #include < string .h >
3 #include < cmath >
4 using namespace std;
5
6 char s[ 10 ][ 10 ];
7 int scx,scy,oux,ouy,sum,n,m,l,flag;
8 int dir[ 4 ][ 2 ] = {{ - 1 , 0 },{ 1 , 0 },{ 0 , - 1 },{ 0 , 1 }};
9
10 void back( int x, int y, int step)
11 {
12 int ecx,ecy,i;
13 if (x == oux && y == ouy && step == l)
14 flag = 1 ;
15 if (flag)
16 return ;
17 if (step > l)
18 return ;
19 if (sum + 1 < l - step)
20 return ;
21 for (i = 0 ;i < 4 ;i ++ )
22 {
23 ecx = x + dir[i][ 0 ];
24 ecy = y + dir[i][ 1 ];
25 if (s[ecx][ecy] != ' X ' && ecx >= 0 && ecy >= 0 && ecx < n && ecy < m)
26 {
27 s[ecx][ecy] = ' X ' ;
28 sum -- ;
29 back(ecx,ecy,step + 1 );
30 s[ecx][ecy] = ' . ' ;
31 sum ++ ;
32 }
33 }
34 }
35
36 int main()
37 {
38 int i,j;
39 while (cin >> n >> m >> l,m + n + l)
40 {
41 sum = 0 ;
42 for (i = 0 ;i < n;i ++ )
43 scanf( " %s " ,s[i]);
44 for (i = 0 ;i < n;i ++ )
45 for (j = 0 ;j < m;j ++ )
46 {
47 if (s[i][j] == ' D ' )
48 {
49 oux = i;
50 ouy = j;
51 } else if (s[i][j] == ' S ' )
52 {
53 scx = i;
54 scy = j;
55 } else if (s[i][j] == ' . ' )
56 sum ++ ;
57 }
58 if (sum + 1 < l)
59 {
60 cout << " NO " << endl;
61 continue ;
62 }
63 if ((abs(oux - scx) + abs(ouy - scy)) % 2 != l % 2 )
64 {
65 cout << " NO " << endl;
66 continue ;
67 }
68 flag = 0 ;
69 s[scx][scy] = ' X ' ;
70 back(scx,scy, 0 );
71 if (flag)
72 {
73 cout << " YES " << endl;
74 }
75 else
76 {
77 cout << " NO " << endl;
78 }
79 }
80 return 0 ;
81 }

感谢你的观赏!!!

转载于:https://www.cnblogs.com/jackes/archive/2011/03/26/1996449.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值