日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

蓝桥杯C++深度优先搜索(dfs)之组队,迷宫,走方格

發(fā)布時間:2023/12/18 c/c++ 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 蓝桥杯C++深度优先搜索(dfs)之组队,迷宫,走方格 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

題目一:組隊(回溯法)

介紹:

題目:

?代碼(C++遞歸)

卡點①

卡點②?

題目二:迷宮

題目三:走方格?

這篇文章主要目的是借各種題目🍌學(xué)習(xí)深度優(yōu)先搜索🍌(depth-first search)

😄純新手0.o😊

題目一:組隊(回溯法)

介紹:

👹👹深度優(yōu)先搜索:

簡稱深搜或者👍爆搜(沒有什么是暴力解決不了的

目的是遍歷,是無序的。過程是:

1、訪問頂點v
2、依次從v的未被訪問的鄰接點出發(fā),對圖進(jìn)行深度優(yōu)先遍歷;直至圖中所有和v有路徑相通的頂點被訪問💪
3、若此時圖中尚有頂點未被訪問,則從一個未被訪問的頂點出發(fā),重新進(jìn)行深度優(yōu)先遍歷,直到圖中所有頂點均被訪問過為止

看圖:

?路徑:

a? b? d? h? d? b? e? i? e? j? e? b? a? c? f? k? f? c? g(橙色表示初次經(jīng)過)

過程描述:

第一條路訪問了a,b,d,h,走到底了,就從h退回d,發(fā)現(xiàn)節(jié)點d沒有除h以外的沒訪問過的,就退回b,b有除d以外未訪問過的e,所以又從e開始進(jìn)行dfs...

被訪問的順序:

a --> b --> d --> h --> e --> i --> j --> c --> f --> k --> g

當(dāng)然初始是隨機(jī)的,它可以先從a到c,也可以先從a到b?

dfs一般找不到最優(yōu)解,所以它適合給了初始條件,尋找解但不要求找最優(yōu)解的題目

👹👹回溯法:

目的是求解過程,是有序的。回溯算法 =?樹的深度優(yōu)先搜索 + 剪枝函數(shù),是dfs的一種改進(jìn)

一般用遞歸實現(xiàn)

題目:

2019藍(lán)橋杯C/C++B組ヽ(?゚▽゚)ノ

作為籃球隊教練,你需要從以下名單中選出 1 號位至 5 號位各一名球員,
組成球隊的5人首發(fā)陣容。
每位球員擔(dān)任 1 號位至 5 號位時的評分如下表所示。請你計算首發(fā)陣容 1
號位至 5 號位的評分之和最大可能是多少?

?代碼(C++遞歸)

#include<iostream> #include<algorithm>//max() using namespace std;int a[20][6] = //聲明初始化二維數(shù)組存儲表格數(shù)據(jù) {{1,97,90,0,0,0},{2,92,85,96,0,0},{3,0,0,0,0,93},{4,0,0,0,80,86},{5,89,83,97,0,0},{6,82,86,0,0,0},{7,0,0,0,87,90},{8,0,97,96,0,0},{9,0,0,89,0,0},{10,95,99,0,0,0},{11,0,0,96,97,0},{12,0,0,0,93,98},{13,94,91,0,0,0},{14,0,83,87,0,0},{15,0,0,98,97,98},{16,0,0,0,93,86},{17,98,83,99,98,81},{18,93,87,92,96,98},{19,0,0,0,89,92},{20,0,99,96,95,81} };//因為是聲明二維數(shù)組,最后這里要加上";" int visit[20];//記錄20個隊員中誰被訪問過 int max_score = 0;//聲明全局變量max_score保存dfs函數(shù)里的最大值//index表示當(dāng)前位置, sum是當(dāng)前組合總分 void dfs(int index, int sum) {if(index == 6)//已經(jīng)選完5個人,可以比較總分了{(lán)max_score = max(max_score, sum);//第一次敲我漏了這個return;}for(int i = 0; i < 20; i++)//遍歷20個隊員{if(!visit[i])//如果他沒被訪問{visit[i] = 1;//已被訪問dfs(index+1, sum+a[i][index]);//在函數(shù)參數(shù)實現(xiàn)了累加visit[i] = 0;//繼續(xù)嘗試下一種5人組合}} }int main() {dfs(1,0);cout<<max_score<<endl;return 0; }

輸出:? 490?

卡點①

代碼39~45行,for循環(huán)的遍歷中,dfs的遞歸,開始有點懵😫

so, 草稿紙上列出index, sum, i在第一種情況的大小?

index? ? ? ? sum?i
1? ? ? ?a[0][1]0
2a[0][1]+a[1][2]1
3? ... + a[2][3]2
4? ... + a[3][4]3
5? ... + a[4][5]4

index = 5時,就完成了5個隊員分?jǐn)?shù)的相加

卡點②?

代碼37行,if(index == 6)后的return;

不清楚index到了6后,是如何返回原來的值的

下面看解析:

先分析遞歸函數(shù)中的return ,看代碼👇👇

#include<iostream> using namespace std;int Sum(int n) {cout<<n<<" ";//讓大家看下遞歸累加順序if (n <= 1)//終止條件, 且Sum(1) == 1return n;return n+Sum(n - 1);//遞歸累加 }int main() {int n;while(cin>>n){int a = Sum(n);//累加和cout<<endl<<a<<endl;cout<<endl;} }

輸入輸出

5 5 4 3 2 1 1510 10 9 8 7 6 5 4 3 2 1 5520 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 210

分析
1,C++ 遞歸函數(shù)中的return是指:
從被調(diào)用函數(shù)返回到主調(diào)函數(shù)中繼續(xù)執(zhí)行,并非一遇到return整個遞歸結(jié)束

2,return 語句,顧名思義是終止當(dāng)前正在執(zhí)行的函數(shù)并將控制權(quán)返回到調(diào)用該函數(shù)的地方

3,在void的函數(shù)中也可以多次使用return,功能和循環(huán)中的break一樣,在中間位置提前退出正在執(zhí)行函數(shù),也就是回到原來位置執(zhí)行下一行代碼

4,return; 表示結(jié)束本次函數(shù)

5,?遞歸中的return常用來作為遞歸終止的條件,當(dāng)達(dá)到遞歸終止條件時,首先return的是最底層調(diào)用的函數(shù),return之后,繼續(xù)執(zhí)行上一層調(diào)用該函數(shù)之后的代碼?

在我對return進(jìn)行理解時,這篇文章給了我一定啟發(fā)關(guān)于遞歸中return的理解(最淺顯易懂)_Pledgee的博客-CSDN博客_遞歸函數(shù)return怎么理解

🔒首先1,2,3,4分別占據(jù)1,2,3,4位置,5號位置就可以依次讓隊員5-20占據(jù);然后4號位給5號隊員,又是一種新的情況,5號位可以依次給6-20號位占據(jù);依次這樣搜索,每個人都可以換個位置。
??其實就是一個排列組合問題,在20個人中選擇五個人,依次排列
??

🔒所以說,index到了6后,返回原來遞歸位置的下一步,return到index=5,然后五號位 通過i ++,由5號隊員占據(jù),到6號占據(jù),一直到20號,接著return到四號位index=4,i++使5號隊員占據(jù)4號位,index+1,index = 5,五號位 i 又由6到20占據(jù)... ...

看圖

題目二:迷宮


基礎(chǔ)概念:

1,棧中的“先進(jìn)后出,后進(jìn)先出”什么意思

棧類似于彈匣,就像裝子彈壓彈進(jìn)彈匣一樣,一粒一粒壓進(jìn)去,但是退子彈是從最上面開始的,最先壓進(jìn)去的最后彈出來,最后一個壓進(jìn)去的第一個彈出來,這就是“先進(jìn)后出”,也叫“后進(jìn)先出

2,棧的定義

?棧就是數(shù)據(jù)暫時存儲的地方,所以才有進(jìn)棧出棧的說法

3,棧與隊列的區(qū)別

棧是把子彈子彈壓進(jìn)彈匣,后進(jìn)的先出;隊列就像排隊,你第一個排,那就第一個輪到你,這就是先進(jìn)先出,也叫后進(jìn)后出。dfs(深度優(yōu)先搜索)應(yīng)用,而bfs(廣度優(yōu)先搜索)應(yīng)用隊列。棧占用空間小,而堆中的bfs常用于最短路。

4,棧在計算機(jī)領(lǐng)域的解釋

棧作為一種數(shù)據(jù)結(jié)構(gòu),是只能在一端進(jìn)行插入和刪除的特殊線性表,它按照后進(jìn)先出的原則存儲數(shù)據(jù),先進(jìn)入的數(shù)據(jù)被壓入棧底,最后的數(shù)據(jù)在棧頂,需要讀數(shù)據(jù)的時候從棧頂開始讀。允許進(jìn)行插入和刪除操作的一段稱為棧頂(top),另一端稱為棧底(bottom)。棧底固定,而棧頂浮動;棧中元素個數(shù)為0時成為空棧。插入數(shù)據(jù)稱為進(jìn)棧(PUSH),刪除數(shù)據(jù)稱為退棧(POP),棧也稱后進(jìn)先出表。棧在函數(shù)調(diào)用時可以可以存儲斷點,做遞歸時要用到棧!

5,堆和棧的區(qū)別

快捷但自由度小,堆過程長但自由度大

6,內(nèi)存分配

一個由C/C++編譯的程序占用的內(nèi)存分為以下幾部分:

(1)棧區(qū)(stack)--由編譯器自動分配釋放,存放函數(shù)參數(shù)值,局部變量的值等。操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧

(2)堆區(qū)(heap)--由程序員分配釋放,若程序員不釋放,程序結(jié)束時可能由OS回收。它與數(shù)據(jù)結(jié)構(gòu)中的堆是兩回事,分配方式類似鏈表

(3)全局(靜態(tài))區(qū)(static)--初始化的全局變量和靜態(tài)變量在一塊區(qū)域,未初始化的在相鄰的另一塊區(qū)域。

(4)文字常量區(qū)--常量字符串放在這里

(5)程序代碼區(qū)--存放函數(shù)體的二進(jìn)制代碼

7,關(guān)于dfs,只要遞歸理解了,相關(guān)語法學(xué)習(xí)(這個我還沒學(xué))并練習(xí)過,也就差不多了

還涉及到:malloc函數(shù),stack(?;緮?shù)據(jù)結(jié)構(gòu)),pop()函數(shù),結(jié)構(gòu)體還有相關(guān)頭文件等,害,沒時間搞了,我先把C++基礎(chǔ)語法學(xué)完再回來

最后奉上幾張圖

?

?

?第二第三張圖片來源于以下博客

迷宮算法(DFS)_熱愛編程的大忽悠的博客-CSDN博客_迷宮算法

以下是我在學(xué)習(xí)dfs過程中看的博客,就差在了語法不懂,先去MOOC學(xué)習(xí)吧:

1,最短路徑問題(更新)_skycrygg的博客-CSDN博客_最短路徑問題

2,c++深度優(yōu)先搜索詳解_練習(xí)時長六年半的Programmer的博客-CSDN博客_c++深度優(yōu)先搜索

3,回溯法與深度優(yōu)先搜索(DFS)_lonely喆的博客-CSDN博客_回溯法和深度優(yōu)先算法區(qū)別

4,深度優(yōu)先搜索(DFS) 總結(jié)(算法+剪枝+優(yōu)化總結(jié))_HeartFireY的博客-CSDN博客

5,迷宮算法(DFS)_熱愛編程的大忽悠的博客-CSDN博客_迷宮算法

6,BFS和DFS_shiki11111的博客-CSDN博客_dfs和bfs

題目三:走方格?

題目

給定一個m*n方格陣,沿著方格邊線走,從左上角(0, 0)開始,每次只能往右或往下走一個單位距離,問走到右下角(m, n)一共有多少種不同走法

輸入

一行包含兩個整數(shù) m 和 n (m >= 1 && m <= 10) && (n >= 1 && n <= 10)

輸出

輸出一個整數(shù),表示走法數(shù)量

代碼

#include<iostream> using namespace std;int m, n, num = 0;int dfs(int x, int y) {if(x == m && y == n)num++;//走法數(shù)量+1else{if(x < m)dfs(x + 1, y);//遞歸行加一if(y < n)dfs(x, y + 1);//遞歸列加一} }int main() {while(cin>>m>>n){dfs(0, 0);cout<<num<<endl;num = 0;}return 0; }

輸入輸出

1 1 2 1 2 3 2 2 6 2 3 10 3 3 20 10 10 184756

分析?

1,首先我們明確,只能向右或下走,然后看圖

圖上粗線表示第一次路徑,代碼的關(guān)鍵在于第13行和第15行對dfs的遞歸,這也是深度優(yōu)先搜索的精髓

當(dāng)?shù)谝淮螡M足x == 2 && y == 3后,此時已到達(dá)(2, 3),函數(shù)會return回上一步,也就是(2, 2),但是下一步的路之前走過了,所以又返回到(2, 1),以此類推一直return到(1, 0),

開始第二條路徑: (1, 0) --> (1, 1) --> (1, 2) --> (1, 3) --> (2, 3)...然后繼續(xù)重復(fù)上述步驟

關(guān)于遞歸的理解其實沒什么好方法,首先你得知道你敲出dps(x + 1, y)類似代碼會出現(xiàn)什么樣的結(jié)果,多做點考察dfs的題,自然就懂了

總結(jié)

以上是生活随笔為你收集整理的蓝桥杯C++深度优先搜索(dfs)之组队,迷宫,走方格的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。