渣渣ACM日记——1010-Tempter of the Bone (HDOJ)

来源:互联网 发布:linux 设置 acl 编辑:程序博客网 时间:2024/05/22 06:44

Tempter of the Bone

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 85369 Accepted Submission(s): 23264


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 5S.X...X...XD....3 4 5S.X...X....D0 0 0

Sample Output
NOYES
/*
刚看到题目,感觉瞬秒的题目,结果被虐得很惨,首先题目要求在第T秒刚好到达,这个没看清楚,其次,传统的dfs这里会超时,n m都小于7还超时,HDOJ的数据量估计很大!换在NYOJ直接就过了。这题目看了解题报告才会,别人博客说是奇偶剪枝 他写的很好 这里引用他的
原文地址:点击打开链接
原文分析:

这个题目用一般的搜索无法完成,因为题目要求在指定的时间内完成,所以只好一步一步来啦,用DFS解决

但是如果这样结果会超时,网上说是用一种奇偶剪枝的方法来间断搜索时间,下面是剪枝的简单理论,一看就懂:

                          把map看作

                             0 1 0 1 0 1
                             1 0 1 0 1 0
                             0 1 0 1 0 1
                             1 0 1 0 1 0
                             0 1 0 1 0 1

                       从 0->1 需要奇数步

                       从 0->0 需要偶数步
                       那么设所在位置 (x,y) 与 目标位置 (dx,dy)

                       如果abs(x-y)+abs(dx-dy)为偶数,则说明 abs(x-y) 和 abs(dx-dy)的奇偶性相同,需要走偶数步

                       如果abs(x-y)+abs(dx-dy)为奇数,那么说明 abs(x-y) 和 abs(dx-dy)的奇偶性不同,需要走奇数步

                       理解为 abs(si-sj)+abs(di-dj) 的奇偶性就确定了所需要的步数的奇偶性!!

                       而 (ti-setp)表示剩下还需要走的步数,由于题目要求要在 ti时 恰好到达,那么  (ti-step) 与 abs(x-y)+abs(dx-dy) 的奇偶性必须相同

                       因此 temp=ti-step-abs(dx-x)-abs(dy-y) 必然为偶数!

本人理解:他的思路是判断该位置与目标位置是否奇偶一致,就是如果不一致,你怎么走也不可能在刚好t走到目标位置.

abs(x-y)+abs(ex-ey) //该位置到目标位置需要走奇或偶数步

t-sum //剩下多少步到t

然后看2者是否吻合;

*/
//我自己的代码:
#include <iostream>#include <string>#include <cmath>using namespace std;int n,m,t;char map[15][15];int next_step[4][2]={{-1,0},{0,1},{1,0},{0,-1}};bool ok;bool book[15][15];int ex,ey; int main(){    void dfs(int x,int y,int sum);    int i,j,ax,ay;    while(cin>>n>>m>>t){        if(n==0&&m==0&&t==0)        break;           ok=0;        for(i=0;i<n;i++)        for(j=0;j<m;j++){            book[i][j]=0;              cin>>map[i][j];              if(map[i][j]=='S'){                  ax=i;ay=j;              }               if(map[i][j]=='D'){                  ex=i;ey=j;              }        }         if(n*m<t||(int)(abs(ax-ay)+abs(ex-ey))%2!=t%2){        cout<<"NO"<<endl;        continue;        }        book[ax][ay]=1;        dfs(ax,ay,0);        if(ok)        cout<<"YES"<<endl;        else            cout<<"NO"<<endl;     }    return 0;}void dfs(int x,int y,int sum){    int i;    if(sum>t||ok)    return;    if(map[x][y]=='D'&&sum==t){        ok=1;        return;    }    if((int)(abs(x-y)+abs(ex-ey))%2!=(t-sum)%2)       return;    for(i=0;i<4;i++){        int a=x+next_step[i][0];        int b=y+next_step[i][1];        if(a<0||a>=n||b<0||b>=m||map[a][b]=='X'||book[a][b]==1)        continue;        book[a][b]=1;        dfs(a,b,sum+1);        if(ok)        return;        book[a][b]=0;    }}/* C++   传统DFS做法,没有有效剪枝,超时 #include <iostream>#include <string>using namespace std;int n,m,t;char map[15][15];int next_step[4][2]={{-1,0},{0,1},{1,0},{0,-1}};bool ok;bool book[15][15];int main(){    void dfs(int x,int y,int sum);    int i,j,ax,ay;    while(cin>>n>>m>>t){        if(n==0&&m==0&&t==0)        break;        ok=0;        for(i=0;i<n;i++)        for(j=0;j<m;j++){            book[i][j]=0;              cin>>map[i][j];              if(map[i][j]=='S'){                  ax=i;ay=j;              }        }        book[ax][ay]=1;        dfs(ax,ay,0);        if(ok)        cout<<"YES"<<endl;        else            cout<<"NO"<<endl;     }    return 0;}void dfs(int x,int y,int sum){    int i;    if(sum>t||ok)    return;    if(map[x][y]=='D'&&sum==t){        ok=1;        return;    }    for(i=0;i<4;i++){        int a=x+next_step[i][0];        int b=y+next_step[i][1];        if(a<0||a>=n||b<0||b>=m||map[a][b]=='X'||book[a][b]==1)        continue;        book[a][b]=1;        dfs(a,b,sum+1);        if(ok)        return;        book[a][b]=0;    }}*//*  C 传统DFS做法,没有有效剪枝,超时 #include <stdio.h>int n,m,t;char map[15][15];int next_step[4][2]={{-1,0},{0,1},{1,0},{0,-1}};int ok;int book[15][15];int main(){    void dfs(int x,int y,int sum);    int i,j,ax,ay;    char s[15];    while(scanf("%d%d%d",&n,&m,&t)==3){        if(n==0&&m==0&&t==0)        break;        ok=0;        for(i=0;i<n;i++){            scanf("%s",s);        for(j=0;j<m;j++){            book[i][j]=0;             map[i][j]=s[j];              if(map[i][j]=='S'){                  ax=i;ay=j;              }        }    }        book[ax][ay]=1;        dfs(ax,ay,0);        if(ok)    printf("YES\n");        else            printf("NO\n");    }    return 0;}void dfs(int x,int y,int sum){    int i;    if(sum>t||ok)    return;    if(map[x][y]=='D'&&sum==t){        ok=1;        return;    }    for(i=0;i<4;i++){        int a=x+next_step[i][0];        int b=y+next_step[i][1];        if(a<0||a>=n||b<0||b>=m||map[a][b]=='X'||book[a][b]==1)        continue;        book[a][b]=1;        dfs(a,b,sum+1);        if(ok)        return;        book[a][b]=0;    }}*/


0 0