HDU 1010第一道剪枝的DFS
2012-05-27 00:54
316 查看
自己写果断超时了,看了大神的剪枝,果然好强悍,附上剪枝
题目大意:这道题就是讲有一只狗要吃骨头,结果进入了一个迷宫陷阱,迷宫里每走过一个地板费时一秒,该地板就会在下一秒塌陷,所以你不能在该地板上逗留。迷宫里面有一个门,只能在特定的某一秒才能打开,让狗逃出去。现在题目告诉你迷宫的大小和门打开的时间,问你狗可不可以逃出去,可以就输出YES,否则NO。
解题思路:这道题,要用到剪枝搜索来做,否则会超时。剪掉的条件是,如果可走地板数目小于给定的时间,绝对不可能得救。还有就是狗走到门的时间必须和题目给定的时间是同奇同偶的,否则也不能在指定的那秒到达门,也不可能得救,剪掉这两种情况后。就用深度搜索来做。从起点出发,深搜周围的路,走过的路就标记为不可走,一直搜索下去,如果搜索失败就回溯,恢复原数据,把可能的路都搜索一遍过去,看看是否有可行方案。
关于剪枝,没有剪枝的搜索不太可能,一个是奇偶剪枝,一个是路径剪枝
奇偶剪枝:
把矩阵标记成如下形式:
0,1,0,1,0
1,0,1,0,1
0,1,0,1,0
1,0,1,0,1
很明显,如果起点在0 而终点在1 那显然 要经过奇数步才能从起点走到终点,依次类推,奇偶相同的偶数步,奇偶不同的奇数步
在读入数据的时候就可以判断,并且做剪枝,当然做的时候并不要求把整个矩阵0,1刷一遍,读入的时候起点记为(Si,Sj) 终点记为(Di,Dj) 判断(Si+Sj) 和 (Di+Dj) 的奇偶性就可以了
路径剪枝:
矩阵的大小是N*M 墙的数量记为num 如果能走的路的数量 N*M - num 小于时间T,就是说走完也不能到总的时间的,这显然是错误的,可以直接跳出了
剪枝3:就是记录当前点到终点的最短路,如果小于剩余的时间的话,就跳出
题目大意:这道题就是讲有一只狗要吃骨头,结果进入了一个迷宫陷阱,迷宫里每走过一个地板费时一秒,该地板就会在下一秒塌陷,所以你不能在该地板上逗留。迷宫里面有一个门,只能在特定的某一秒才能打开,让狗逃出去。现在题目告诉你迷宫的大小和门打开的时间,问你狗可不可以逃出去,可以就输出YES,否则NO。
解题思路:这道题,要用到剪枝搜索来做,否则会超时。剪掉的条件是,如果可走地板数目小于给定的时间,绝对不可能得救。还有就是狗走到门的时间必须和题目给定的时间是同奇同偶的,否则也不能在指定的那秒到达门,也不可能得救,剪掉这两种情况后。就用深度搜索来做。从起点出发,深搜周围的路,走过的路就标记为不可走,一直搜索下去,如果搜索失败就回溯,恢复原数据,把可能的路都搜索一遍过去,看看是否有可行方案。
关于剪枝,没有剪枝的搜索不太可能,一个是奇偶剪枝,一个是路径剪枝
奇偶剪枝:
把矩阵标记成如下形式:
0,1,0,1,0
1,0,1,0,1
0,1,0,1,0
1,0,1,0,1
很明显,如果起点在0 而终点在1 那显然 要经过奇数步才能从起点走到终点,依次类推,奇偶相同的偶数步,奇偶不同的奇数步
在读入数据的时候就可以判断,并且做剪枝,当然做的时候并不要求把整个矩阵0,1刷一遍,读入的时候起点记为(Si,Sj) 终点记为(Di,Dj) 判断(Si+Sj) 和 (Di+Dj) 的奇偶性就可以了
路径剪枝:
矩阵的大小是N*M 墙的数量记为num 如果能走的路的数量 N*M - num 小于时间T,就是说走完也不能到总的时间的,这显然是错误的,可以直接跳出了
剪枝3:就是记录当前点到终点的最短路,如果小于剩余的时间的话,就跳出
#include<stdio.h> #include<math.h> #include<string.h> typedef struct { int x; int y; }position; position exit,move[4]={-1,0,0,1,1,0,0,-1}; char maze[10][10]; int visited[10][10],t,sum; bool found; void dfs(position,int ); void wall(int r,int c); void findenter(position &,position&,int ,int ); int main() { position enter; int r,c,i; while(scanf("%d %d %d",&r,&c,&t)&&r+c+t) { sum=0; found=false; memset(visited,0,sizeof(visited)); for(i=1;i<=r;i++) scanf("%s",&maze[i][1]); wall(r,c); findenter(enter,exit,r,c); if(sum+1<t) { printf("NO\n"); continue; } dfs(enter,0); if(found) printf("YES\n"); else printf("NO\n"); } return 0; } void wall(int r,int c) { int i; for(i=0;i<=r+1;i++) { maze[i][0]='X'; maze[i][c+1]='X'; } for(i=0;i<=c+1;i++) { maze[0][i]='X'; maze[r+1][i]='X'; } } void findenter(position &enter,position &exit,int r,int c) { int i,j; for(i=1;i<=r;i++) for(j=1;j<=c;j++) { if(maze[i][j]=='.') sum++; else if(maze[i][j]=='S') { enter.x=i; enter.y=j; } else if(maze[i][j]=='D') { exit.x=i; exit.y=j; } } } void dfs(position now,int step) { int i,temp; position next; if(found) return ; if(maze[now.x][now.y]=='D'&&step==t) { found=true; return; } temp=t-step-abs(now.x-exit.x)-abs(now.y-exit.y); if(temp<0||temp%2) return ; visited[now.x][now.y]=1; for(i=0;i<4;i++) { next.x=now.x+move[i].x; next.y=now.y+move[i].y; if(!visited[next.x][next.y]&&maze[next.x][next.y]!='X') { visited[next.x][next.y]=1; dfs(next,step+1); visited[next.x][next.y]=0; } } }
相关文章推荐
- HDU 1010第一道剪枝的DFS
- HDU 1010 Tempter of the Bone (dfs + 剪枝)
- HDU 5305 Friends(DFS + 剪枝)
- HDU 1010 Tempter of the Bone(DFS + 剪枝)
- HDU——1584 蜘蛛牌(剪枝 + dfs)
- hdu 5167 Fibonacci(DFS,剪枝,斐波那契)
- HDU 1010 Tempter of the Bone (DFS+剪枝)
- hdu 1584 蜘蛛牌【dfs+简单剪枝】
- hdu 4090 GemAnd Prince dfs+bfs+最优性剪枝
- hdu 4109 dfs+剪枝优化
- hdu1010 dfs+剪枝
- hdu 5113 Black And White (dfs回溯+剪枝)
- hdu 2616 暴力使用 dfs求最短路径(剪枝有点依稀)
- (Vivid Vervet )dfs——一道好题(抓住剪枝)hdu1010
- hdu 1010 DFS+剪枝
- HDU 5323 Solve this interesting problem(dfs结合线段树特点剪枝)
- HDU 4431 Mahjong (DFS,暴力枚举,剪枝)
- HDU 1010 Tempter of the Bone (ZOJ 2110) DFS+剪枝
- HDU 1010 Tempter of the Bone(逃离地狱,DFS,剪枝,错题集)
- HDU 4848-Wow! Such Conquering!(DFS+最优性剪枝)