今天继续dfs的训练,遇到了一道神题,不停地TLE,我DD都快碎了。。。。。好在经过本渣不懈努力,还是弄了出来,不容易啊,发上来纪念一下,顺便总结一下关于用dfs解决规定路程的问题。
先上题目:
//基本思路:通过回溯(即return回来后)把标记的改为未标记的从而得到所有路径 #include<stdio.h> #include<cstdlib> int r,c,t,x,y,x1,y1; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; char point[7][7]; bool flag; int count; int map[7][7];//能够帮助去掉不可能的情况,不用就TLE void dfs(int x0,int y0,int r,int c,int step)//step记录当前点在当前路径的步数 { int temp; temp=count-step-abs(x0-x1)-abs(y0-y1)+1;//通过对当前点和最终点的位置判断当前点有无可能满足条件,不用就TLE if (temp<0||temp%2==1)//这是通过奇偶判断,数学知识,易忽视。。 return; for(int i=0;i<4;i++) { int tempx=x0+dx[i],tempy=y0+dy[i]; if(point[tempy][tempx]=='D'&&step==count)//判断步数与路径长度是否相同 flag=true; if(tempx>=0&&tempx<c&&tempy>=0&&tempy<r&&point[tempy][tempx]=='.') { point[tempy][tempx]='X';//通过使当前点变为X来标记当前路径是否经过 dfs(tempx,tempy,r,c,step+1);//探索邻接点 point[tempy][tempx]='.';//回溯还原,使其得能够探索全部路径 if(flag==true)//如果存在,就直接返回,不用此判断就TLE。。。 return ; } } return ; } int main() { for(int i=0;i<7;i++) for(int j=0;j<7;j++) { if((i+j)%2) map[i][j]=0; else map[i][j]=1; } while(1) { scanf("%d%d%d",&r,&c,&t); getchar(); if(r==0&&c==0&&t==0) break; count=t; for(int i=0;i<r;i++) { scanf("%s",point[i]); } for(int i=0;i<r;i++) for(int j=0;j<c;j++) { if(point[i][j]=='S') { y=i; x=j; } else if(point[i][j]=='D') { y1=i; x1=j; } } if(abs(map[y1][x1]-map[y][x])%2!=t%2)//map判断起点终点的位置是否有可能,不用就TLE。。 { printf("NO "); continue; } flag=false; dfs(x,y,r,c,1); if(flag) printf("YES "); else printf("NO "); } return 0; }
map的用处:
v可以把map看成这样:
v0 1 0 1 0 1
v1 0 1 0 1 0
v0 1 0 1 0 1
v1 0 1 0 1 0
v0 1 0 1 0 1
v从为 0的格子走一步,必然走向为
1的格子
v从为 1的格子走一步,必然走向为
0的格子
v即:
v0->1或1->0必然是奇数步
v0->0走1->1必然是偶数步
所以当遇到从 0走向0或从1走向1但是要求时间是奇数的,或者,从1 走向 0 但是要求时间是偶数的都可以直接判断不可达!
所以map表能从一开始就减少可能的情况。