广搜(初见)
以下是廣搜水題
題意:輸入一個n*n的迷宮,輸入從起點(diǎn)到終點(diǎn)的最短路
輸入:
12 ?//迷宮大小
2 9 11 8 //起點(diǎn)和終點(diǎn)
1 1 1 1 1 1 1 1 1 1 1 1 ?//鄰接矩陣,0表示通,1表示不通
1 0 0 0 0 0 0 1 0 1 1 1
1 0 1 0 1 1 0 0 0 0 0 1
1 0 1 0 1 1 0 1 1 1 0 1
1 0 1 0 0 0 0 0 1 0 0 1
1 0 1 0 1 1 1 1 1 1 1 1
1 0 0 0 1 0 1 0 0 0 0 1
1 0 1 1 1 0 0 0 1 1 1 1
1 0 0 0 0 0 1 0 0 0 0 1
1 1 1 0 1 1 1 1 0 1 0 1
1 1 1 1 1 1 1 0 0 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
輸出:
(2,9)->(3,9)->(3,8)->(3,7)->(4,7)->(5,7)->(5,6)->(5,5)->(5,4)->(6,4)->(7,4)->(7,3)->(7,2)->(8,2)->(9,2)->(9,3)->(9,4)->(9,5)->(9,6)->(8,6)->(8,7)->(8,8)->(9,8)->(9,9)->(10,9)->(11,9)->(11,8)
27
代碼:
#include<cstdio> using namespace std; int dwax[4]={0,0,1,-1},dway[4]={1,-1,0,0}; int n,m,state[2501][2],father[2501],px,py,x,y,head,tail,s; bool a[51][51]; void write(int x,int dep) { if (x==0) return;//如果到x則0則為返回完畢 s++; write(father[x],dep+1);//返回 printf("(%d,%d)",state[x][0],state[x][1]);//輸出路徑 if (dep!=0) printf("->"); } void bfs() { head=0;//預(yù)處理 tail=1; do { head+=1;//出隊(duì) x=state[head][0]; y=state[head][1]; for (int i=0;i<4;i++) if (!a[x+dwax[i]][y+dway[i]] && x+dwax[i]<=n && y+dway[i]<=n && x+dwax[i]>=1 && y+dway[i]>=1)//判斷是否可以通行{tail++;//入隊(duì)father[tail]=head;state[tail][0]=x+dwax[i];state[tail][1]=y+dway[i];a[x+dwax[i]][y+dway[i]]=true;//封路if (x+dwax[i]==px && y+dway[i]==py)//判斷終點(diǎn){write(tail,0);return;}} }while (head<tail);//如果隊(duì)列空了則退出} int main() {scanf("%d%d%d%d%d",&n,&x,&y,&px,&py);int q=0;for (int i=1;i<=n;i++)for (int j=1;j<=n;j++){scanf("%d",&q);if (q==1) a[i][j]=true;}//以上為輸入不解釋state[1][0]=x;state[1][1]=y;a[x][y]=true;bfs();printf("\n%d",s); }題目2:騎士旅行
在一個n m 格子的棋盤上,有一只國際象棋的騎士在棋盤的左下角 (1;1)(如圖1),騎士只能根據(jù)象棋的規(guī)則進(jìn)行移動,要么橫向跳動一格縱向跳動兩格,要么縱向跳動一格橫向跳動兩格。 例如, n=4,m=3 時,若騎士在格子(2;1) (如圖2), 則騎士只能移入下面格子:(1;3),(3;3) 或 (4;2);對于給定正整數(shù)n,m,I,j值 (m,n<=50,I<=n,j<=m) ,你要測算出從初始位置(1;1) 到格子(i;j)最少需要多少次移動。如果不可能到達(dá)目標(biāo)位置,則輸出"NEVER"。
輸入:
5 3
1 2
輸出:
3
代碼:
#include<cstdio> using namespace std; int dwax[8]={1,1,-1,-1,2,2,-2,-2},dway[8]={2,-2,2,-2,1,-1,1,-1}; int n,m,state[2501][3],father[2501],px,py,x,y,head,tail,s; bool a[51][51]; void write(int x)//檢測bug的攻擊 {if (x==0) return;s++;write(father[x]);printf("[%d , %d]->[%d , %d]\n",state[father[x]][0],state[father[x]][1],state[x][0],state[x][1]);//輸出路徑 } void bfs() {head=0;//初始化不解釋tail=1;do{head+=1;//出隊(duì)x=state[head][0];y=state[head][1];for (int i=0;i<8;i++) if (!a[x+dwax[i]][y+dway[i]] && x+dwax[i]<=n && y+dway[i]<=m && x+dwax[i]>=1 && y+dway[i]>=1)//判斷可否通行{tail++;father[tail]=head;state[tail][0]=x+dwax[i];state[tail][1]=y+dway[i];state[tail][2]=state[head][2]+1;a[x+dwax[i]][y+dway[i]]=true;//封路if (x+dwax[i]==px && y+dway[i]==py){//write(tail);s=state[tail][2];return;}} }while (head<tail);//空隊(duì)列結(jié)束廣搜 } int main() {scanf("%d%d%d%d",&m,&n,&px,&py);state[1][0]=1;state[1][1]=1;state[1][2]=1;a[1][1]=true;//輸入初始化不解釋bfs();if (head==tail) printf("NEVER");else printf("%d",s-1);//輸出不解釋 }題目3:翻幣問題
有N個硬幣(6<=N<=20000)全部正面朝上排成一排,每次將其中5個硬幣翻過來放在原位置,直到最后全部硬幣翻成反面朝上為止。試編程找出步數(shù)最少的翻法,輸出最少步數(shù)及翻法。
輸入:
6
輸出:
6
代碼:
#include<cstdio> using namespace std; int state[20001],father[20001],head,tail,s,n; bool ok[20001]; void print(int x)//返回輸出 {if (x==0) return;print(father[x]);//printf("%d:%d\n",s,state[x]);s++; } void bfs() {state[1]=n;head=0;tail=1;do{head++;//出隊(duì)for (int i=0;i<=5;i++)//翻得硬幣正面?zhèn)€數(shù)if (state[head]>=i && n-state[head]>=5-i)//如果正面和反面數(shù)量足夠{tail++;//入隊(duì)father[tail]=head;//記錄父節(jié)點(diǎn)state[tail]=state[head]-i+5-i;//翻if (ok[state[tail]])//判斷有沒有重復(fù){tail--;continue;}ok[state[tail]]=true;//封if (state[tail]==0)//判斷結(jié)束{print(tail);return;}}}while (head<tail);//結(jié)束隊(duì)列 } int main() {scanf("%d",&n);bfs();printf("%d",s-1);//輸出 }題目4:最優(yōu)乘車
H城是一個旅游勝地,每年都有成千上萬的人前來觀光。為方便游客,巴士公司在各個旅游景點(diǎn)及賓館,飯店等地都設(shè)置了巴士站并開通了一些單程巴上線路。每條單程巴士線路從某個巴士站出發(fā),依次途經(jīng)若干個巴士站,最終到達(dá)終點(diǎn)巴士站。?
一名旅客最近到H城旅游,他很想去S公園游玩,但如果從他所在的飯店沒有一路已士可以直接到達(dá)S公園,則他可能要先乘某一路巴士坐幾站,再下來換乘同一站臺的另一路巴士, 這樣換乘幾次后到達(dá)S公園。?
現(xiàn)在用整數(shù)1,2,…N 給H城的所有的巴士站編號,約定這名旅客所在飯店的巴士站編號為1…S公園巴士站的編號為N。?
寫一個程序,幫助這名旅客尋找一個最優(yōu)乘車方案,使他在從飯店乘車到S公園的過程中換車的次數(shù)最少。?
題目很煩是吧!
輸入:
3 7
6 7
4 7 3 6
2 1 3 5
輸出:
2
代碼:
#include<cstdio> using namespace std; int a,k,bus[101][101],num[101][101],state[10001][3],head,tail,s,n,m; char c; bool ok[101]; void bfs() {head=0;tail=1;state[1][0]=0;state[1][1]=1;state[1][2]=0;//初始化不解釋do{head++;for (int i=1;i<=num[state[head][1]][0];i++)//枚舉當(dāng)前站可以到達(dá)的站{if (ok[num[state[head][1]][i]]) continue;//去重ok[num[state[head][1]][i]]=true;//封tail++;state[tail][1]=num[state[head][1]][i];state[tail][0]=state[head][0]+1;//狀態(tài)讀入if (state[tail][1]==n)//判斷結(jié)束{s=state[tail][0];return;}}}while(head<=tail); } int main() {scanf("%d%d",&m,&n);scanf("\n");for (int i=1;i<=m;i++){while ((c=getchar())!='\n'){if (c!=' ') a=a*10+c-48;//讀取數(shù)字else {k++;bus[i][k]=a;//記錄該公交線for (int j=1;j<k;j++) {num[bus[i][j]][0]++;num[bus[i][j]][num[bus[i][j]][0]]=a;//記錄該點(diǎn)可以到達(dá)哪站}a=0;}}k++;bus[i][k]=a;for (int j=1;j<k;j++) {num[bus[i][j]][0]++;num[bus[i][j]][num[bus[i][j]][0]]=a;}//最后一個的處理a=0;bus[i][0]=k;k=0;}//以上為預(yù)處理bfs();if (s==0) printf("NO");else printf("%d",s-1); }好了,初見題就那么多。
總結(jié)