hdu1010(dfs加剪枝)

Problem Description
The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze began to shake, and the doggie could feel the ground sinking. He realized that the bone was a trap, and he tried desperately to get out of this maze.

The maze was a rectangle with sizes N by M. There was a door in the maze. At the beginning, the door was closed and it would open at the T-th second for a short period of time (less than 1 second). Therefore the doggie had to arrive at the door on exactly the T-th second. In every second, he could move one block to one of the upper, lower, left and right neighboring blocks. Once he entered a block, the ground of this block would start to sink and disappear in the next second. He could not stay at one block for more than one second, nor could he move into a visited block. Can the poor doggie survive? Please help him.
 

Input
The input consists of multiple test cases. The first line of each test case contains three integers N, M, and T (1 < N, M < 7; 0 < T < 50), which denote the sizes of the maze and the time at which the door will open, respectively. The next N lines give the maze layout, with each line containing M characters. A character is one of the following:

'X': a block of wall, which the doggie cannot enter; 
'S': the start point of the doggie; 
'D': the Door; or
'.': an empty block.

The input is terminated with three 0's. This test case is not to be processed.
 

Output
For each test case, print in one line "YES" if the doggie can survive, or "NO" otherwise.
 

Sample Input
   
   
   
   
4 4 5 S.X. ..X. ..XD .... 3 4 5 S.X. ..X. ...D 0 0 0
 

Sample Output
   
   
   
   
NO YES

注意,这道题目是要恰好t时间到达,并不是在t时间内到达......不然一个bfs轻松的就过了。。。。

这题dfs需要剪枝,就这题而言,需要两种方法同时剪枝!

奇偶剪枝:

把矩阵标记成如下形式:

0,1,0,1,0

1,0,1,0,1

0,1,0,1,0

1,0,1,0,1

很明显,如果起点在0 而终点在1 那显然 要经过奇数步才能从起点走到终点,依次类推,奇偶相同的偶数步,奇偶不同的奇数步

在读入数据的时候就可以判断,并且做剪枝,当然做的时候并不要求把整个矩阵0,1刷一遍,读入的时候起点记为(Si,Sj) 终点记为(Di,Dj) 判断(Si+Sj) 和 (Di+Dj) 的奇偶性就可以了

路径剪枝:

矩阵的大小是N*M 墙的数量记为wall 如果能走的路的数量 N*M - wall 小于时间T,就是说走完也不能到总的时间的,这显然是错误的,可以直接跳出了

对于路径剪枝一个判断就ok了,对于奇偶剪枝,很多人的代码都写在了dfs里面,其实理解了含义也是直接一个判断的事儿搞定啊!根本不需要进dfs~

#include <iostream>
#include <stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char a[10][10];
int m,n,t,fx[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int sx,sy,ex,ey,min0;
bool esc;//用esc记录是否找到终点且时间恰好符合条件
void dfs(int x,int y,int cnt)
{
    if(cnt==t&&x==ex&&y==ey)
    {
        esc=1;return;
    }
        for(int i=0;i<4;i++)
        {
            int tx=x+fx[i][0],ty=y+fx[i][1];
            if(tx>=0&&tx<n&&ty>=0&&ty<m&&a[tx][ty]!='X')
            {
               a[tx][ty]='X';
               dfs(tx,ty,cnt+1);
               if(esc)return;
               a[tx][ty]='.';
            }
        }
}

int main()
{

    while(cin>>n>>m>>t&&!(n==0&&m==0&&t==0))
    {
        int ss=0;
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
            for(int j=0;j<m;j++)
            {
                if(a[i][j]=='S')sx=i,sy=j;
                else if(a[i][j]=='D')ex=i,ey=j;
                else if(a[i][j]=='X')ss++;
            }
        }
        int tem1=(sx+sy)%2,tem2=(ex+ey)%2;
        if((tem1==tem2&&t%2==1)||(tem1!=tem2&&t%2==0))//奇偶剪枝
            {
                printf("NO\n");continue;
            }
        if(n*m-ss<=t)//路径剪枝
            {
                printf("NO\n");continue;
            }
        esc=0;
        a[sx][sy]='X';
        dfs(sx,sy,0);
        if(esc)printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

你可能感兴趣的:(搜索,ACM,大二)