LQ训练营(C++)学习笔记_广度优先搜索
這里寫目錄標題
- 四、廣度優先搜索
- 1、隊列的概念
- 2、小朋友報數問題
- 2.1 問題描述
- 2.2 代碼實現
- 3、廣度優先搜索概念
- 4、走迷宮問題
- 4.1 問題描述
- 4.2 代碼實現
- 5、過河卒問題
- 5.1 問題描述
- 5.2 代碼實現
四、廣度優先搜索
1、隊列的概念
隊列是一種線性的數據結構,和棧一樣是一種運算受限制的線性表。只允許從表的前端(front)進行刪除操作,而在表的后端(rear)進行插入操作。
C++中queue的實現在一個<queue>頭文件中,在代碼開頭引入這個頭文件,并在引入所有頭文件后加上一句using namespace std
C++中直接構造一個queue的語句為:queue<T>q。這樣定義一個名為q的存儲T類型數據的隊列。
2、小朋友報數問題
2.1 問題描述
借助隊列完成報數游戲的計算,假設有 n個小朋友,報到m的小朋友退出游戲。有n個小朋友做游戲,他們的編號分別是1,2,3…n。他們按照編號從小到大依次順時針圍成一個圓圈,第一個小朋友從1開始報數,依次按照順時針方向報數(報數的值加一),每個報m的人會離開隊伍,然后下一個小朋友會繼續從1開始報數,直到只剩下一個小朋友為止。
求最后一位小朋友的編號。
2.2 代碼實現
#include<iostream> #include<queue> using namespace std; int main(){int n,m;cin>>n>>m;queue<int>q;//定義一個int類型的隊列qfor(int i=1;i<=n;i++){q.push(i);}int cur=1;while(q.size()>1){int x=q.front();//從隊首取出一個小朋友q.pop;if(cur==m){//如果報數是m就退出游戲cur=1;}else{//如果不是m,則重新入隊q.push(x);cur++;}}cout<<q.front()<<endl;//輸出剩下小朋友的編號return 0; }3、廣度優先搜索概念
廣度優先搜索,又稱寬度優先搜索,簡稱bfs,先將與起始點距離較近的點搜索完畢,再繼續搜索較遠的點,一層層的擴展。
bfs需要借助隊列來實現:
4、走迷宮問題
4.1 問題描述
迷宮是許多小方格構成的矩形,在每個小方格中有的是墻(用1表示),有的是路(用0表示)。走迷宮就是從一個小方格沿上、下、左、右四個方向到鄰近的方格,當然不能穿墻。
實現生成迷宮(從文本中讀取數據生成),輸出迷宮(圖案方式),探索迷宮路徑(最短路徑),輸出迷宮路徑(圖案方式)。
4.2 代碼實現
#include <iostream> #include <string> #include <queue> using namespace std; int n, m; string maze[110]; bool vis[110][110]; int dir[4][2] = {{‐1, 0}, {0, ‐1}, {1, 0}, {0, 1}}; bool in(int x, int y) {return 0 <= x && x < n && 0 <= y && y < m; } struct node{int x,y,d;node(int xx,int yay,int dd){//定義結構體,記錄坐標x,y以及當前使用的步數dx=xx;y=yy;d=dd;} }; int bfs(int sx,int sy){queue<node>q;q.push(node(sx,sy,0));vis[sx][sy]=true;while(!q.empty()){//隊列中有元素時,取出隊首元素node now=q.front();q.pop();for(int i=0;i<4;i++){//從隊列中取出點去擴展其他的點int tx=now.x+dir[i][0];int ty=now.y+dir[i][1];if(int(tx,ty)&&maze[tx][ty]!=‘*’&&!vis[tx][ty]){//(tx,ty)合法且沒有被訪問if(maze[tx][ty]==‘T’){//如果是終點,直接返回return now.d+1;}else{//不是終點,把這個點標記訪問并壓入棧中vis[tx][ty]=true;q.push(node(tx,ty,now.d+1));}}}}return -1;//沒有訪問到終點,返回-1,表示沒有找到起點到終點的路徑 } int main() {cin >> n >> m;for (int i = 0; i < n; i++) {cin >> maze[i];}int x, y;for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (maze[i][j] == 'S') {x = i, y = j;}}}cout<<bfs(x,y)<<endl;return 0; }5、過河卒問題
5.1 問題描述
棋盤上A點有一個過河卒,需要走到目標B點。卒行走的規則:可以向下、或者向右。同時在棋盤上的任一點有一個對方的馬(如C點),該馬所在的點和所有跳躍一步可達的點稱為對方馬的控制點,如圖中的C點和P1,……,P8,卒不能通過對方馬的控制點。棋盤用坐標表示,A點(0,0)、B點(n, m)(n,m為不超過20的整數),同樣馬的位置坐標是需要給出的,C≠A且C≠B。現在要求你計算出卒從A點能夠到達B點的路徑的條數。
5.2 代碼實現
#include<iostream> using namespace std; int dir[8][2]={{1,2},{1,-2},{2,1},{2,-1},{-1,2},{-1,-2},{-2,-1}}; bool d[30][30];//用于標記馬的控制點,該位置卒不能通過 int main(){int n,m,cx,cy;//n,m是棋盤的大小,cx,cy是馬的位置cin>>n>>m>>cx>>cy;d[cx][cy]=true;for(int i=0;i<8;i++){int tx=cx+dir[i][0];int ty=cy+dir[i][1];if(tx>=0&&tx<=n&&ty>=0&&ty<=m){d[tx][ty]=true;}}dp[0][0]=1;//能走到位置(i,j)的方案數量,先初始化然后進行遞推for(int i=0;i<=n;i++){for(int j=0;j<=m;j++){if(d[i][j]==false){//遞推公式dp[i][j]=dp[i-1][j]+dp[i][j-1],為防止數組越界,把i和j分開處理。if(i){dp[i][j]+=dp[i-1][j];}if(j){dp[i][j]+=dp[i][j-1];}}}}cout<<dp[n][m]<<endl;return 0; }總結
以上是生活随笔為你收集整理的LQ训练营(C++)学习笔记_广度优先搜索的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一加Ace 2原神定制礼盒4月登场!香菱
- 下一篇: LQ训练营(C++)学习笔记_动态规划入