HDOJ(1010)DFS+剪枝
阿新 • • 發佈:2019-02-09
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;View Codereturn; } 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; }
深度優先搜尋(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(); // 彈出佇列頭結點 }