1. 程式人生 > >1月 D - 逃離迷宮 HDU - 1728-復雜dfs的剪枝

1月 D - 逃離迷宮 HDU - 1728-復雜dfs的剪枝

pri 出發 col else 數據 手動 測試數據 while 包含

    給定一個m × n (m行, n列)的迷宮,迷宮中有兩個位置,gloria想從迷宮的一個位置走到另外一個位置,當然迷宮中有些地方是空地,gloria可以穿越,有些地方是障礙,她必須繞行,從迷宮的一個位置,只能走到與它相鄰的4個位置中,當然在行走過程中,gloria不能走到迷宮外面去。令人頭痛的是,gloria是個沒什麽方向感的人,因此,她在行走過程中,不能轉太多彎了,否則她會暈倒的。我們假定給定的兩個位置都是空地,初始時,gloria所面向的方向未定,她可以選擇4個方向的任何一個出發,而不算成一次轉彎。gloria能從一個位置走到另外一個位置嗎? 
Input
      第1行為一個整數t (
1 ≤ t ≤ 100),表示測試數據的個數,接下來為t組測試數據,每組測試數據中,   第1行為兩個整數m, n (1 ≤ m, n ≤ 100),分別表示迷宮的行數和列數,接下來m行,每行包括n個字符,其中字符.表示該位置為空地,字符*表示該位置為障礙,輸入數據中只有這兩種字符,每組測試數據的最後一行為5個整數k, x 1, y 1, x 2, y 2 (1 ≤ k ≤ 10, 1 ≤ x 1, x 2 ≤ n, 1 ≤ y 1, y 2 ≤ m),其中k表示gloria最多能轉的彎數,(x 1, y 1), (x 2, y 2)表示兩個位置,其中x 1,x 2對應列,y 1, y 2對應行。 Output   每組測試數據對應為一行,若gloria能從一個位置走到另外一個位置,輸出“yes”,否則輸出“no”。 Sample Input
2 5 5 ...** *.**. ..... ..... *.... 1 1 1 1 3 5 5 ...** *.**. ..... ..... *.... 2 1 1 1 3 Sample Output no yes

用dfs遍歷走的情況,看可不可以到終點,需要指出的是,在同一個可能面朝的方向不同,需要儲存方向這個參數

於是就遍歷嘛,上下左右都走一遍,其實我寫的時候就知道一定會超時的,但就不想剪枝(小聲逼逼

於是就tle了 (手動托臉

剪枝 :如果走了走過的格子,此時可轉彎數還少,情況就一定被走過的包含了,考慮了方向:

//turn是剩的可轉的彎數,dic是方向參數

if(cnt_t[y][x][dic]<=turn)cnt_t[y][x][dic]=turn;
    else return false;

這次過了,用時200ms

但總覺得哪裏不對

就算方向不同,turn數多的話turn一下就走那個方向了,所以方向並不重要,如果turn小的話直接剪掉就好了

//就像這樣...

    if(cnt_t[y][x]<=turn)cnt_t[y][x]=turn;
        else return false;

可等是因為如果之前走過而沒到終點的話,不如換個方向再試試

進一步剪了後只用15ms;

ac代碼:

#include<cstdio>
#include<cstring>
#define N 1
#define E 2
#define S 3
#define W 4
using namespace std;
int x1,x2,y1,y2,m,n,turns,flag=0,cnt_t[110][110];
char pic[110][110];
bool dfs(int y,int x,int dic,int turn){
    if(cnt_t[y][x]<=turn)cnt_t[y][x]=turn;
    else return false;
    if(flag)return true;
    if(turn<0) return false;
    if(x<1||y<1||x>n||y>m||pic[y][x]==*)return false;//printf("here %d %d\n",x,y);
    if(x==x2&&y==y2){flag=1; return true;}
    if(dic==N){
        dfs(y+1,x,N,turn);
        dfs(y,x-1,W,turn-1);
        dfs(y,x+1,E,turn-1);
    }
    else if(dic==E){
        dfs(y,x+1,E,turn);
        dfs(y+1,x,N,turn-1);
        dfs(y-1,x,S,turn-1);
    }
    else if(dic==S){
        dfs(y-1,x,S,turn);
        dfs(y,x-1,W,turn-1);
        dfs(y,x+1,E,turn-1);
    }
    else if(dic==W){
        dfs(y,x-1,W,turn);
        dfs(y+1,x,N,turn-1);
        dfs(y-1,x,S,turn-1);
    }
    return true;
}

int main(){
    int t;
    scanf("%d",&t) ;
    while(t--){
        memset(cnt_t,0,sizeof(cnt_t));
        flag=0;
        scanf("%d%d",&m,&n);
        for(int i=1;i<=m;i++)
        scanf("%s",pic[i]+1);
        scanf("%d%d%d%d%d",&turns,&x1,&y1,&x2,&y2);
        dfs(y1,x1,N,turns);
        dfs(y1,x1,E,turns);
        dfs(y1,x1,S,turns);
        dfs(y1,x1,W,turns);
        if(flag)printf("yes\n");
        else printf("no\n");    
        } 
    return 0;
}

1月 D - 逃離迷宮 HDU - 1728-復雜dfs的剪枝