1. 程式人生 > >HDOJ(1010)DFS+剪枝

HDOJ(1010)DFS+剪枝

Tempter of the Bone

#include <stdio.h>
#include <stdlib.h>
char map[10][10];
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
bool flag;
int n,m,xd,yd,t;

void DFS(int x,int y,int t)
{
    if(t==0)        //到時間了符合條件flag=true再退出,不符合條件直接退出。
    {
        if(x==xd&&y==yd)
            flag=true;
        
return; } int temp=abs(x-xd)+abs(y-yd)-t; if(temp>0||temp&1) //temp&1相當於temp%2,但是temp%2會超時,位運算比較快 return; //奇偶性剪枝+最小步數大於時間剪枝 if(flag) return; //找到解後還有部分在繼續搜尋,這句是為了讓其它搜尋停止 int i; int next_x,next_y; for(i=0;i<4;i++) { next_x
=x+dx[i]; next_y=y+dy[i]; if(next_x>=1&&next_x<=m&&next_y>=1&&next_y<=n&&map[next_y][next_x]!='X') { map[next_y][next_x]='X'; DFS(next_x,next_y,t-1); map[next_y][next_x]='.'; //回溯,如果搜不到D,還要恢復成原來的路徑
} } } int main() { int i,j; int x,y; while(scanf("%d%d%d",&n,&m,&t)!=EOF) { if(n==0&&m==0&&t==0) break; int wall=0; for(i=1;i<=n;i++) { scanf("%s",map[i]+1); //儘量用%s, %c容易出錯 for(j=1;j<=m;j++) { if(map[i][j]=='S') { x=j; y=i; } if(map[i][j]=='D') { xd=j; yd=i; } if(map[i][j]=='X') wall++; } } if(n*m-wall<=t) //可以走的格子比時間少,直接剪掉 printf("NO\n"); else { flag=false; map[y][x]='X'; DFS(x,y,t); if(flag) printf("YES\n"); else printf("NO\n"); } } return 0; }
View Code

深度優先搜尋(DFS):解決迷宮問題(比如:能否逃離迷宮,只要判斷能不能)

遞迴式基本框架:(不同的深搜程式碼千變萬化)

void dfs(int si,int sj,int t)      //si,sj為起始位置X行Y列座標
{
    int i;
    if(si==di&&sj==dj&&t>=0)       // di,dj為目標位置,t為剩餘時間,k為標記符號,可以就k=1
        k=1;                       // 能否在t時間內移動到座標(di,dj)位置(逃離迷宮)?                                
    if(si>=n||si<0||sj>=m||sj<0) 
        return;    //防止走到地圖外面去
    if(k)
        return;                   //終止條件,找到能出去的方法就直接return,不執行下面語句
    for(i=0;i<4;i++)  //dir[4][2]={1,0,0,1,-1,0,0,-1} 表示方向 :上下左右
    {
        if(map[si+dir[i][0]][sj+dir[i][1]]!='X')
        {
            map[si+dir[i][0]][sj+dir[i][1]]='X';  //把走過的地方標記成 X,防止又往回走,
                                                  //(走來走去就死迴圈啦!)
            dfs(si+dir[i][0],sj+dir[i][1],t-1);  // 遞迴,進一步搜尋下去
            map[si+dir[i][0]][sj+dir[i][1]]='.'; //用回溯法,如果上面的深搜失敗,就把圖還原到原來的狀態
        }
    }
}

廣度優先搜尋(BFS):適用解決最優解問題 (如:用時最少;代價最優;)

核心程式碼框架:

while(佇列不為空)
{
    node temp=Q.front();
    //從該結點狀態轉移到其他狀態
    for(int i=0;i<4;i++) //int go[4][2] = {1,0,-1,0,0,1,0,-1}; 上下左右
    {
        int x=temp.x+go[i][0];
        int y=temp.y+go[i][1];
        int t=temp.t+1;
        //有選擇的選擇未出現過的狀態入隊 (用到雜湊法,不明白的就百度一下 hash 吧)
        if(hash[x][y]==false&&該點可行的條件)
        {
            if(x==dx&&y==dy)     // 判斷該狀態是否為目的狀態
                return t;     
            hash[x][y]=true;
            Q.push(newnode(x,y,t));
        }
    }
    Q.pop();      // 彈出佇列頭結點
}