标签:c++ iostream namespace 编程 递归
4 4 5 S.X. ..X. ..XD .... 3 4 5 S.X. ..X. ...D 0 0 0
NO YES
代码如下:
#include <iostream> using namespace std; const int dx[4]= {1,-1,0,0}; const int dy[4]= {0,0,1,-1}; char str[7][7]; int N,M,T,k,n; bool dir(int x,int y) { return x>=0&&y>=0&&x<N&&y<M; //判断是否在区域内 } void findpath(int x,int y) { int nx,ny,i; char tmp=str[x][y]; //先将原来的位置信息记录 str[x][y]='X'; //将走过的位置更改为X; k++; for (i=0; i<4; i++) //向四个方向搜索 { nx=x+dx[i]; ny=y+dy[i]; if (dir(nx,ny)&&str[nx][ny]!='X') //如果在区域内且该位置不为X; { if (str[nx][ny]=='D') //如果到达的位置是点D { if (k+1==T) //此时k还没有加1,比较k+1与预计的步数T { n=1; //如果相等,则n改为1; break; } } else { findpath(nx,ny); //递归 if (n==1) //如果n为1,跳出循环。 break; } } } str[x][y]=tmp; //回退 k--; //回退 } int main() { int i,j; int x,y,tx,ty; while (cin>>N>>M>>T) { n=0; if (N==0||M==0||T==0) break; for (i=0; i<N; i++) { for (j=0; j<M; j++) { cin>>str[i][j]; if (str[i][j]=='S') //记录起始位置S的信息 { x=i; y=j; } else if (str[i][j]=='D') //记录末尾位置D的信息 { tx=i; ty=j; } } } if (((T%2==0) && ((x+y)%2==(tx+ty)%2)) || ((T%2==1) && ((x+y)%2!=(tx+ty)%2))) //深度搜索黑白棋 { k=-1; findpath(x,y); } if (n==0) //如果n为0,则说明不能 cout<<"NO"<<endl; else //否则能 cout<<"YES"<<endl; } return 0; }
题目大意是给定一个区域,区域内有S和D两个点,问S到D能否用给定的步数到达(多或少都不行)(X是不能通过的位置)。
思路还是递归回溯法,不过这里又用到了一种叫深度搜索黑白棋的方法,用来排除注定走不到的“死路”,而且需要注意的是,由于可能有些路径不能在给定的步数到达,然后需要返回,需要把计数的k值回归到在某一位置开始搜索时的步数,所以在findpath的函数中需要先记录原先的位置,在搜索不成功后又返回到原先的位置。
深度搜索:在深度优先搜索的过程当中,往往有很多走不通的“死路”。假如我们把这些“死路”排除在外,不是可以节省很多的时间吗?打一个比方,前面有一个路径,别人已经提示:“这是死路,肯定不通”,而你的程序仍然很“执着”地要继续朝这个方向走,走到头来才发现,别人的提示是正确的。这样,浪费了很多的时间。针对这种情况,我们可以把“死路”给标记一下不走,就可以得到更高的搜索效率。
深度搜索黑白棋:在国际象棋盘中,棋格是黑白相间的,如果步数T是偶数的话,末尾的颜色和起始的颜色是相同的;如果步数T是奇数,则首尾颜色是不同的。如果是和本题类似的题目用到这种方法,可以排除很多死路。
标签:c++ iostream namespace 编程 递归
原文地址:http://blog.csdn.net/liuchang54/article/details/43926977