标签: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