Curling 2.0 DFS+回溯+剪枝
来源:互联网 发布:上海安畅网络 编辑:程序博客网 时间:2024/05/22 12:32
http://poj.org/problem?id=3009
大致题意:一只冰壶在n*m的格子上运动,0代表空地,1代表石头,2代表起点(可走),3代表终点(不可走).
冰壶在运动过程中,每次只朝一个方向移动直到遇到石头1或终点3。若遇到3,到达终点不再移动;若遇到1,则停在当前位置(注意并不替代石头位置),石头位置由1变为0,然后冰壶改变方向继续移动。
还有,若冰壶一直走到边界也没遇到石头或终点,那么这条路是不可行的。
问冰壶从2到3的最小步数,步数的计算方法是冰壶运动过程中方向的改变次数。
注意的是:
冰壶撞到石头后,冰壶会停在石头前面,此时(静止状态)才允许改变冰壶的运动方向,而该块石头会破裂,石头所在的区域由1变为0. 也就是说,冰壶撞到石头后,并不会取代石头的位置。
终点是一个摩擦力很大的区域,冰壶若到达终点3,就会停止在终点的位置不再移动。
解题思路:
要先明确:
0为滑动区域
1为石头区域
2为起点,也是可滑动区域
3为终点,不可滑动区域
(1) 起点为“2”,也是一个可滑动的区域,所以标记起点位置之后,可以把起点当做0
(2) 注意区分冰壶是运动的还是静止的,若是静止的话,旁边1格有石头是不能走的。
(3) 输出冰壶从2到3的最短路,如果最短路的步数大于10(不包括10),视作无法走到终点(其实这是用来剪枝的)
(4) 滑动过程中冰壶不允许出界
基于上面的原则,不难发现:
(1)所谓的“走一步”,就是指冰壶从一个静止状态到下一个静止状态,就是说冰壶在运动时经过的“格数”不视作“步数”,也就是说冰壶每次移动的距离都是不定的。
(2)还有就是由于石头会因为冰壶的碰撞而消失,因此冰壶每“走一步”,场地的环境就会改变一次。
(3)基于(2),可以发现本题虽然是要找 “最短路”,但是BFS几乎不可能,因为每“走一步”,场地的状态就要改变一次;而如果该步不满足要求,又要求把场地的状态还原到前一步,这只有DFS能做到。
(4)基于(3),DFS不是BFS,不能简单地用它来找最短路,必须要把所有可能的路一一找出来,再逐一比较它们的步数才能确定最短。但题目值允许1000MS,此时就面临一个超时的问题。所以题目才同时给出“步数超过10则视为失败”的条件,这是用来剪枝的
有了上面的分析,就能最终确定本题的解法了:
DFS+回溯+剪枝
#include <stdio.h>#include<string.h>int w,h;//记录场地的宽和高int sx,sy,ex,ey;//记录起点和终点坐标int dx[4]={0,0,-1,1};//存方向变化量int dy[4]={1,-1,0,0};int maps[30][30],best;//best记录最优解。maps存地图void dfs(int cx,int cy,int step)//cx,cy记录当前位置。step表示已走多少步{ int nx,ny,i; if(step>best)//剪枝如果大于目前最优解直接返回 return; for(i=0;i<4;i++) { nx=cx+dx[i]; ny=cy+dy[i]; if(nx>=h||nx<0||ny>=w||ny<0||maps[nx][ny]==1)//越界或立即有阻挡物剪枝 continue; while(nx<h&&nx>=0&&ny<w&&ny>=0&&maps[nx][ny]!=1)//一直滑 { if(nx==ex&&ny==ey)//若到终点 { if(step+1<best) best=step+1; break; } nx+=dx[i]; ny+=dy[i]; } if(nx==ex&&ny==ey)//若由于到终点跳出去 continue; if(nx<h&&nx>=0&&ny<w&&ny>=0) { maps[nx][ny]=0;//若是碰到阻挡物。阻挡物消失。 dfs(nx-dx[i],ny-dy[i],step+1);//继续搜索 maps[nx][ny]=1;//还原阻挡物。回溯 } }}int main(){ int i,j; while(scanf("%d%d",&w,&h),w||h) { best=12;//初始化best for(i=0;i<h;i++)//读取地图 for(j=0;j<w;j++) { scanf("%d",&maps[i][j]); if(maps[i][j]==2) sx=i,sy=j; if(maps[i][j]==3) ex=i,ey=j; } dfs(sx,sy,0);//深搜 if(best<=10) printf("%d\n",best); else printf("-1\n"); } return 0;}
- Curling 2.0 DFS+回溯+剪枝
- POJ3009 Curling 2.0(dfs+剪枝)
- Curling 2.0 DFS+回溯+减枝
- poj3009 Curling 2.0(DFS回溯)
- pku 3009 Curling 2.0 DFS+剪枝
- POJ3009 Curling 2.0(DFS+剪枝)
- POJ 3009-Curling 2.0(dfs+剪枝)
- POJ 3009 Curling 2.0 (dfs剪枝)
- poj 3009 Curling 2.0 dfs回溯
- POJ 3009 Curling 2.0【带回溯DFS】
- dfs + 回溯 +剪枝
- hdu 5113(dfs+剪枝+回溯)
- Curling 2.0 poj DFS
- POJ3009:Curling 2.0(DFS)
- Curling 2.0(DFS)
- POJ3009 Curling 2.0(DFS)
- POJ3009 Curling 2.0 DFS
- POJ3009 Curling 2.0【DFS】
- 设计模式第二章 策略模式
- [手工搬运][程序系统托盘与运行实例唯一实现]
- 嵌入式系统开发之环境的建立
- 《红高粱》式优化
- 通达OA 2013版和2013增强版两个版本开发的一些差异
- Curling 2.0 DFS+回溯+剪枝
- Chrome浏览器缓存目录修改
- 第十周项目4
- 第十周 项目三血型统计
- Codeforces Round #160 (Div. 2)---A. Roma and Lucky Numbers
- 程序设计:三角形类型判断
- 如何重新编译linux内核
- FusionCharts 2D圆盘代码
- [VIM]命令笔记