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