1月 D - 逃离迷宫 HDU - 1728-复杂dfs的剪枝
给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有些地方是障碍,她必须绕行,从迷宫的一个位置,只能走到与它相邻的4个位置中,当然在行走过程中,gloria不能走到迷宫外面去。令人头痛的是,gloria是个没什么方向感的人,因此,她在行走过程中,不能转太多弯了,否则她会晕倒的。我们假定给定的两个位置都是空地,初始时,gloria所面向的方向未定,她可以选择4个方向的任何一个出发,而不算成一次转弯。gloria能从一个位置走到另外一个位置吗? Input 第1行为一个整数t (1 ≤ t ≤ 100),表示测试数据的个数,接下来为t组测试数据,每组测试数据中, 第1行为两个整数m, n (1 ≤ m, n ≤ 100),分别表示迷宫的行数和列数,接下来m行,每行包括n个字符,其中字符'.'表示该位置为空地,字符'*'表示该位置为障碍,输入数据中只有这两种字符,每组测试数据的最后一行为5个整数k, x 1, y 1, x 2, y 2 (1 ≤ k ≤ 10, 1 ≤ x 1, x 2 ≤ n, 1 ≤ y 1, y 2 ≤ m),其中k表示gloria最多能转的弯数,(x 1, y 1), (x 2, y 2)表示两个位置,其中x 1,x 2对应列,y 1, y 2对应行。 Output 每组测试数据对应为一行,若gloria能从一个位置走到另外一个位置,输出“yes”,否则输出“no”。 Sample Input 2 5 5 ...** *.**. ..... ..... *.... 1 1 1 1 3 5 5 ...** *.**. ..... ..... *.... 2 1 1 1 3 Sample Output no yes
用dfs遍历走的情况,看可不可以到终点,需要指出的是,在同一个可能面朝的方向不同,需要储存方向这个参数
于是就遍历嘛,上下左右都走一遍,其实我写的时候就知道一定会超时的,但就不想剪枝(小声逼逼
于是就tle了 (手动托脸
剪枝 :如果走了走过的格子,此时可转弯数还少,情况就一定被走过的包含了,考虑了方向:
//turn是剩的可转的弯数,dic是方向参数 if(cnt_t[y][x][dic]<=turn)cnt_t[y][x][dic]=turn; else return false;
这次过了,用时200ms
但总觉得哪里不对
就算方向不同,turn数多的话turn一下就走那个方向了,所以方向并不重要,如果turn小的话直接剪掉就好了
//就像这样... if(cnt_t[y][x]<=turn)cnt_t[y][x]=turn; else return false;
可等是因为如果之前走过而没到终点的话,不如换个方向再试试
进一步剪了后只用15ms;
ac代码:
#include<cstdio> #include<cstring> #define N 1 #define E 2 #define S 3 #define W 4 using namespace std; int x1,x2,y1,y2,m,n,turns,flag=0,cnt_t[110][110]; char pic[110][110]; bool dfs(int y,int x,int dic,int turn){ if(cnt_t[y][x]<=turn)cnt_t[y][x]=turn; else return false; if(flag)return true; if(turn<0) return false; if(x<1||y<1||x>n||y>m||pic[y][x]=='*')return false;//printf("here %d %d\n",x,y); if(x==x2&&y==y2){flag=1; return true;} if(dic==N){ dfs(y+1,x,N,turn); dfs(y,x-1,W,turn-1); dfs(y,x+1,E,turn-1); } else if(dic==E){ dfs(y,x+1,E,turn); dfs(y+1,x,N,turn-1); dfs(y-1,x,S,turn-1); } else if(dic==S){ dfs(y-1,x,S,turn); dfs(y,x-1,W,turn-1); dfs(y,x+1,E,turn-1); } else if(dic==W){ dfs(y,x-1,W,turn); dfs(y+1,x,N,turn-1); dfs(y-1,x,S,turn-1); } return true; } int main(){ int t; scanf("%d",&t) ; while(t--){ memset(cnt_t,0,sizeof(cnt_t)); flag=0; scanf("%d%d",&m,&n); for(int i=1;i<=m;i++) scanf("%s",pic[i]+1); scanf("%d%d%d%d%d",&turns,&x1,&y1,&x2,&y2); dfs(y1,x1,N,turns); dfs(y1,x1,E,turns); dfs(y1,x1,S,turns); dfs(y1,x1,W,turns); if(flag)printf("yes\n"); else printf("no\n"); } return 0; }