ZOJ:2110 Tempter of the Bone

来源:互联网 发布:解数独的软件 编辑:程序博客网 时间:2024/05/29 04:47

简单回溯。

注意一点,标记该位置已访问要在各种不合理及边界终止条件之后,因为函数从这些地方跳出是不会将该位置改回未访问状态的,别的还好说,如果是终止位置,也就是'D'位置,将导致以后无法访问。总之标记访问状态的位置很重要,还有不要忘了结束的时候改成未访问状态。

 

 

在代码中加入了剪枝。

不剪枝要跑1s,剪枝以后大约400ms。

首先要意识到这么一个事情:从迷宫中的某一特定位置到另一个特定位置,不走重复路径,可以有多条路线,这些路线走的步数相差的步数是2的倍数。

也就是说如果从某点到D的最短距离小于要求走的步数而且相差值是2的倍数,那么是存在可能按要求到达D点的。否则不可能到达。

也就是说当某点到D的距离大于可走步数或者它们差值不是2的倍数这些情况可以剪掉。

 

另外可以在dfs开始前判一下如果X过多使得可走步数小于要求步数可以直接NO。

 

#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;char grid[10][10];int N,M,T,edx,edy;bool vis[10][10];bool ok;void dfs(int I,int J,int D){    if(ok) return;    if(grid[I][J]=='X') return;    if(!(1<=I&&I<=N&&1<=J&&J<=M))return;    if(grid[I][J]=='D')    {        if(D==T) ok=true;        return;    }    int tmp=(T-D)-(abs(I-edx)+abs(J-edy));    if(tmp<0||tmp%2) return;    vis[I][J]=true;    if(!vis[I-1][J])  dfs(I-1,J,D+1);    if(!vis[I][J-1])  dfs(I,J-1,D+1);    if(!vis[I][J+1])  dfs(I,J+1,D+1);    if(!vis[I+1][J])  dfs(I+1,J,D+1);    vis[I][J]=false;}int main(){    while(scanf("%d%d%d",&N,&M,&T)&&!(!N&&!M&&!T))    {        memset(grid,0,sizeof(grid));        memset(vis,false,sizeof(vis));        getchar();        int x,y;        for(int i=1; i<=N; ++i)        {            for(int j=1; j<=M; ++j)            {                scanf("%c",&grid[i][j]);                if(grid[i][j]=='S')                {                    x=i;                    y=j;                }                else  if(grid[i][j]=='D')                {                    edx=i;                    edy=j;                }            }            getchar();        }        ok=false;        dfs(x,y,0);        if(ok) puts("YES");        else puts("NO");    }    return 0;}


 

原创粉丝点击