- 廣度搜索
優點:
目標節點如果存在,用寬度優先搜索算法總可以找到該目標節點,而且是最小(即最短路徑)的節點.
缺點:
當目標節點距離初始節點較遠時,會產生許多無用的節點,搜索效率低.
例題:
#include <iostream> #include <queue> using namespace std; #define MAXN 100010 int n,k; int dis[MAXN]; //步驟數 int bfs(){ memset(dis,-1,sizeof(dis)); //表示未用過 queue<int>q; q.push(n); dis[n]=0; while(!q.empty()){ int x=q.front();q.pop(); if(x==k){return dis[x];} if(x+1>=0 && dis[x+1]==-1){ q.push(x+1); dis[x+1]=dis[x]+1; } if(x-1>=0 && dis[x-1]==-1){ q.push(x-1); dis[x-1]=dis[x]+1; } if(x*2<MAXN && dis[x*2]==-1){ q.push(x*2); dis[x*2]=dis[x]+1; } } return -1; } int main(){ while(cin>>n>>k) cout<<bfs()<<endl; return 0; }
hdu 1026 Ignatius and the Princess I
優先隊列+BFS
#include <iostream> #include <queue> using namespace std; #define INF 1<<31-1; int n,m; char graph[101][101]; int dis[101][101]; int dir[4][2]={-1,0,0,1,1,0,0,-1}; struct point{ int x,y,time; bool operator <(const point b)const{ return time>b.time; } }begin,end,cur,path[101][101],neighbor; int bfs(){ begin.x=0,begin.y=0;begin.time=0; dis[0][0]=0; priority_queue<point>q; q.push(begin); while(!q.empty()){ cur=q.top();q.pop(); if(cur.x==n-1&&cur.y==m-1){ end=cur; return cur.time; } for(int i=0;i<4;i++){ neighbor.x=cur.x+dir[i][0]; neighbor.y=cur.y+dir[i][1]; if(neighbor.x>=0&&neighbor.x<n&&neighbor.y>=0&&neighbor.y<m&&graph[neighbor.x][neighbor.y]!='X'){ if(graph[neighbor.x][neighbor.y]=='.'){ neighbor.time=cur.time+1; } else neighbor.time=cur.time+graph[neighbor.x][neighbor.y]-'0'+1; if(neighbor.time<dis[neighbor.x][neighbor.y]){ dis[neighbor.x][neighbor.y]=neighbor.time; path[neighbor.x][neighbor.y]=cur; q.push(neighbor); } } } } return -1; } int getpath(point next){//遞歸輸出路徑 int t=1,s; point pre; if(next.x==0&&next.y==0) return 0; pre=path[next.x][next.y]; t+=getpath(pre); printf("%ds:(%d,%d)->(%d,%d)\n",t,pre.x,pre.y,next.x,next.y); //FIGHTing... if(graph[next.x][next.y]>='0'&&graph[next.x][next.y]<='9'){ s=graph[next.x][next.y]-'0'; for(int i=t+1;i<=t+s;i++){ printf("%ds:FIGHT AT (%d,%d)\n",i,next.x,next.y); } t+=s; } return t; } int main(){ while(cin>>n>>m){ for(int i=0;i<n;i++) for(int j=0;j<m;j++){ cin>>graph[i][j]; dis[i][j]=INF; } int count=bfs(); if(count!=-1){ printf("It takes %d seconds to reach the target position, let me show you the way.\n",count); getpath(end); cout<<"FINISH"<<endl; } else cout<<"God please help our poor hero.\nFINISH"<<endl; } return 0; }
2. 深度搜索
深度優先搜索也稱爲回溯搜索回溯:能進則進,進不了則換,換不成則退優點
空間需求少,深度優先搜索的存儲器要求是深度約束的線性函數
問題
可能搜索到錯誤的路徑上,在無限空間中可能陷入無限的搜索
最初搜索到的結果不一定是最優的
#include <iostream> using namespace std; int dir[8][2]={-1,-2,1,-2,-2,-1,2,-1,-2,1,2,1,-1,2,1,2}; bool visit[9][9]; int pathx[100]; int pathy[100]; int p,q; bool ok; void dfs(int x,int y,int n){ if(n==p*q){ ok=1; return ; } if(ok) return ; for(int i=0;i<8 && !ok;i++){ int xx=x+dir[i][0]; int yy=y+dir[i][1]; if(xx<1||xx>p||yy<1||yy>q||visit[xx][yy]) continue; visit[xx][yy]=1; pathx[n]=xx; pathy[n]=yy; dfs(xx,yy,n+1); visit[xx][yy]=0; } } void printpath(){ pathx[0]=1; pathy[0]=1; for(int i=0;i<=p*q-1;i++) printf("%c%d",pathy[i]+'A'-1,pathx[i]); cout<<endl<<endl; } int main(){ int t; cin>>t; for(int c=1;c<=t;c++){ cin>>p>>q; printf("Scenario #%d:\n",c); ok=0; memset(visit,0,sizeof visit); memset(pathx,0,sizeof pathx); memset(pathy,0,sizeof pathy); visit[1][1]=1; dfs(1,1,1); if(!ok){ cout<<"impossible"<<endl<<endl; continue; } printpath(); } }
鋪放矩形塊 (IOI 95)
This program is straightforward, but a bit long due to the geometry involved.
There are 24 permutations of the 4 rectangles, and for each permutation, 16 different ways to orient them. We generate all such orientations of permutations, and put the blocks together in each of the 6 different ways, recording the smallest rectangles we find.
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct Rect Rect; struct Rect { int wid; int ht; }; Rect rotate(Rect r) { Rect nr; nr.wid = r.ht; nr.ht = r.wid; return nr; } int max(int a, int b){return a > b ? a : b;} int min(int a, int b){return a < b ? a : b;} int tot; int bestarea; int bestht[101]; void record(Rect r) { int i; if(r.wid*r.ht < tot) *(long*)0=0; if(r.wid*r.ht < bestarea || bestarea == 0) { bestarea = r.wid*r.ht; for(i=0; i<=100; i++) bestht[i] = 0; } if(r.wid*r.ht == bestarea) bestht[min(r.wid, r.ht)] = 1; } void check(Rect *r) { Rect big; int i; /* schema 1: all lined up next to each other */ big.wid = 0; big.ht = 0; for(i=0; i<4; i++) { big.wid += r[i].wid; big.ht = max(big.ht, r[i].ht); } record(big); /* schema 2: first three lined up, fourth on bottom */ big.wid = 0; big.ht = 0; for(i=0; i<3; i++) { big.wid += r[i].wid; big.ht = max(big.ht, r[i].ht); } big.ht += r[3].ht; big.wid = max(big.wid, r[3].wid); record(big); /* schema 3: first two lined up, third under them, fourth to side */ big.wid = r[0].wid + r[1].wid; big.ht = max(r[0].ht, r[1].ht); big.ht += r[2].ht; big.wid = max(big.wid, r[2].wid); big.wid += r[3].wid; big.ht = max(big.ht, r[3].ht); record(big); /* schema 4, 5: first two rectangles lined up, next two stacked */ big.wid = r[0].wid + r[1].wid; big.ht = max(r[0].ht, r[1].ht); big.wid += max(r[2].wid, r[3].wid); big.ht = max(big.ht, r[2].ht+r[3].ht); record(big); /* * schema 6: first two pressed next to each other, next two on top, like: * 2 3 * 0 1 */ big.ht = max(r[0].ht+r[2].ht, r[1].ht+r[3].ht); big.wid = r[0].wid + r[1].wid; /* do 2 and 1 touch? */ if(r[0].ht < r[1].ht) big.wid = max(big.wid, r[2].wid+r[1].wid); /* do 2 and 3 touch? */ if(r[0].ht+r[2].ht > r[1].ht) big.wid = max(big.wid, r[2].wid+r[3].wid); /* do 0 and 3 touch? */ if(r[1].ht < r[0].ht) big.wid = max(big.wid, r[0].wid+r[3].wid); /* maybe 2 or 3 sits by itself */ big.wid = max(big.wid, r[2].wid); big.wid = max(big.wid, r[3].wid); record(big); } void checkrotate(Rect *r, int n) { if(n == 4) { check(r); return; } checkrotate(r, n+1); r[n] = rotate(r[n]); checkrotate(r, n+1); r[n] = rotate(r[n]); } void checkpermute(Rect *r, int n) { Rect t; int i; if(n == 4) checkrotate(r, 0); for(i=n; i<4; i++) { t = r[n], r[n] = r[i], r[i] = t; /* swap r[i], r[n] */ checkpermute(r, n+1); t = r[n], r[n] = r[i], r[i] = t; /* swap r[i], r[n] */ } } int main(void) { Rect r[4]; int i; for(i=0; i<4; i++) scanf( "%d %d", &r[i].wid, &r[i].ht); tot=(r[0].wid*r[0].ht+r[1].wid*r[1].ht+r[2].wid*r[2].ht+r[3].wid*r[3].ht); checkpermute(r, 0); printf( "%d\n", bestarea); for(i=0; i<=100; i++) if(bestht[i]) printf( "%d %d\n", i, bestarea/i); return 0; }
clocks
#include <stdio.h> int a[9][9]= { {3,3,3,3,3,2,3,2,0}, {2,3,2,3,2,3,1,0,1}, {3,3,3,2,3,3,0,2,3}, {2,3,1,3,2,0,2,3,1}, {2,3,2,3,1,3,2,3,2}, {1,3,2,0,2,3,1,3,2}, {3,2,0,3,3,2,3,3,3}, {1,0,1,3,2,3,2,3,2}, {0,2,3,2,3,3,3,3,3} }; int v[9]; int main() { int i,j,k; for (i=0; i<9; i++) { scanf("%d",&k); for(j=0; j<9; j++) v[j]=(v[j]+(4-k/3)*a[i][j])%4; } k=0; for (i=0; i<9; i++) for (j=0; j<v[i]; j++) if (!k) { printf("%d",i+1); k=1; } else printf(" %d",i+1); printf("\n"); return 0; }