HDU-1010-Tempter of the Bone(深搜+奇偶剪枝)

Tempter of the Bone

翻譯:

暑假的時候,小明和朋友去迷宮中尋寶。然而,當他拿到寶貝時,迷宮開始劇烈震動,他感到地面正在下沉,他們意識到這是一個陷阱!他們想盡一切辦法逃出去。
迷宮是一個大小爲 N*M 的長方形,迷宮中有一扇門。一開始,門是關着的,他會在第 t 秒的時間打開。因爲,小明和朋友必須在第 t 秒到大門口。每一秒,他都可以向上下左右四個方向移動一個點。一旦他移動了,他剛纔所在的點就消失,(這意味着他不能回到他已經走過的點)。他不能在一個點上停留超過一秒,並且不能走障礙點。小明和朋友能安全的逃出嗎?

Input
輸入由多個測試用例組成。每個測試用例的第一行包含三個整數 N、M 和 T ( 1 < N , M < 7 ; 0 < T < 50 ),分別表示迷宮的大小和門打開的時間。接下來的N行給出迷宮佈局,每一行包含M個字符。下列字母分別表示:

“X”: 一堵牆,小明和朋友不能在上面停留
“S”: 起點
“D”: 門
“.”: 可以走的點

輸入以 3 個 0 時結束。這個測試用例不需要處理。

Output
對於每組樣例輸出一行。
如果小明能夠安全逃出,輸出 “YES” ,否則輸出 “NO”。

Sample Input

4 4 5
S.X.
…X.
…XD

3 4 5
S.X.
…X.
…D
0 0 0

Sample Output

NO
YES

代碼實現:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

char Map[10][10];   //地圖
int visit[10][10];  //儲存數據標記
int n,m,t,endx,endy,flag;   //n、m、結束座標、標記

void dfs(int startx,int starty,int time)    //開始座標,時間
{
    int dx,dy;
    int dir[4][2]={{-1,0},{1,0},{0,1},{0,-1}};  //上下左右四個方向
    if(flag)        //***很重要,可以減少步驟,如果直接找到路線就直接return
    {
        return;
    }
    if(startx==endx&&starty==endy&&time==t)
    {
        flag=1;
        return;
    }
    int temp=t-time-abs(endx-startx)-abs(endy-starty);  //剪枝代碼
    if(temp<0||temp&1)  		//如果剩餘的步數已經不足以走到出口,且必須是偶數,偶數-偶數=偶數,奇數-奇數=偶數
    {
        return;
    }
    for(int i=0;i<4;i++)
    {
        dx=startx+dir[i][0];
        dy=starty+dir[i][1];
        if(dx<0||dy>=m||dy<0||dx>=n)
        {
            continue;
        }
        if(Map[dx][dy]!='X'&&visit[dx][dy]==0)
        {
            visit[dx][dy]=1;    //標記,判斷能不能走
            dfs(dx,dy,time+1);
            if(flag)            //找到就return
                return;
            visit[dx][dy]=0;    //返回標記,方便下次尋找
        }
    }
    return ;
}

int main()
{
    int startx,starty,wall;     //開始座標、牆
    while(cin>>n>>m>>t)
    {
        if(n==0&&m==0&&t==0)
        {
            break;
        }
        flag=0;wall=0;
        memset(visit,0,sizeof(visit));
        for(int i=0;i<n;i++)    //畫地圖
        {
            scanf("%s",Map[i]);
        }
        for(int i=0;i<n;i++)    //判斷
        {
            for(int j=0;j<m;j++)
            {
                if(Map[i][j]=='S')
                {
                    startx=i;starty=j;
                }
                if(Map[i][j]=='D')
                {
                    endx=i;endy=j;
                }
                if(Map[i][j]=='X')
                {
                    wall++;
                }
            }
        }
        if(t>n*m-wall-1)        //判斷時間與牆數和地圖的關係
        {
            cout<<"NO"<<endl;
            continue;
        }
        visit[startx][starty]=1;    //標記走過的路線
        dfs(startx,starty,0);
        if(flag==1)
        {
            cout<<"YES"<<endl;
        }
        else
        {
            cout<<"NO"<<endl;
        }
    }
    return 0;
}

原題鏈接:
http://acm.hdu.edu.cn/showproblem.php?pid=1010
https://vjudge.net/problem/HDU-1010

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章