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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Firetruck(DFS+回溯)

發布時間:2025/3/20 编程问答 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Firetruck(DFS+回溯) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目描述

中心城市消防部門與運輸部門合作,維護反映城市街道現狀的城市地圖。消防員需要能夠選擇從火警站到火警的路線。
中心城市分為不重疊的消防區。當報告發生火災時,中央調度員通知火災發生地區最近的火警站,并列出可能路線。您必須編寫一個程序,中央調度員可以使用該程序來生成從地區火警站到火災的路線。

輸入

消防區都用小于 21 的正整數來標識,而且火場始終位于第一個消防區。輸入文件包含多個測試用例,代表不同火災。
? 測試用例的第一行由一個整數組成,該整數是距離火災最近的火警站。
? 接下來的幾行由成對的正整數組成,這些成對的正整數是開放街道相鄰的消防區。(例如,如果對 4 7 在一行上,則消防區 4 和消防區 7 之間的街道是開放的。沒有其他消防區在 4 和 7 之間。)
? 每個測試用例的最后一行由一對 0 組成。

輸出

對于每個測試用例,您的輸出必須通過編號來標識用例(”CASE 1:”,”CASE 2:”等)。它必須列出每條路線,并按照字典序從小到大輸出。它必須提供從火警站到火災地點的總路線。
不同用例的輸出必須分開顯示。

樣例輸入

6
1 2
1 3
3 4
3 5
4 6
5 6
2 3
2 4
0 0
4
2 3
3 4
5 1
1 6
7 8
8 9
2 5
5 7
3 1
1 8
4 6
6 9
0 0

樣例輸出

CASE 1:
1 2 3 4 6
1 2 3 5 6
1 2 4 3 5 6
1 2 4 6
1 3 2 4 6
1 3 4 6
1 3 5 6
There are 7 routes from the firestation to streetcorner 6.
CASE 2:
1 3 2 5 7 8 9 6 4
1 3 4
1 5 2 3 4
1 5 7 8 9 6 4
1 6 4
1 6 9 8 7 5 2 3 4
1 8 7 5 2 3 4
1 8 9 6 4
There are 8 routes from the firestation to streetcorner 4.




分析

  • 這道題主要就是要我們按照所給的地圖,找到并按字典序輸出火警到火災地點的所有路徑。


  • 這道題和以往不同的的是,并不是直接給出矩陣地圖,而是通過給出點的連接情況來給出地圖。這很容易讓入門新手無從下手,但是如果你學過數據結構或者離散數學的話,你會知道我們可以把給出的圖用矩陣表示。
    • 首先,我們要以比題目給的最大地點號(本題是21)稍大的值,來創建一個二維數組map[maxn][maxn]。
    • 然后,根據輸入的連通情況,在矩陣上做標記。本題給的是個無向圖,比如:輸入了一個2 6,表示2和6之間連通,就在矩陣二行六列和六行二列的地方標記1(true)。
    • 題目給出樣例一表示的矩陣為:
      0 1 1 0 0 0
      1 0 1 1 0 0
      1 1 0 1 1 0
      0 1 1 0 0 1
      0 0 1 0 0 1
      0 0 0 1 1 0(注意:已經忽略0行0列)


  • 有了矩陣地圖,這道題又可以像以前用搜索解決了。考慮到按字典序輸出,我們用深度優先搜索比較恰當。


  • 這道題的樣例輸入比較麻煩,win7的控制臺不能復制粘貼,如果我們要多次調試,輸入數據會很煩。這里可以用一個,我剛剛學到的小技巧:
    • 首先,在.cpp所在的文件夾中創建一個test.txt文件,接著把要輸入的數據黏貼到該.txt文件中。
    • 然后在main()函數中加入freopen(“test.txt”,”r”,stdin),即可實現文件輸入。(該函數包含在cstdio頭文件中)




代碼如下

#include <iostream> #include <cstring> #include <cstdio> using namespace std; const int maxn=21+4; int map[maxn][maxn]={0};//用來存儲地圖 int mark[maxn];//用來記錄走過的點,以便輸出 bool m[maxn];//用來記憶該點有沒有被訪問過 int n,ans1;//ans1記錄總共有多少條路徑 void dfs(int x,int ans)//x表示所在的地點,ans表示這是去到的第幾個地點 {if(x==n){ans1++;cout<<'1';for(int i=1;i<ans;i++)cout<<' '<<mark[i];cout<<endl;return ;}for(int i=2;i<maxn;i++)//從2開始逐個搜索,因為是從1出發,不能再回到1if(map[x][i]==1&&!m[i])//如果i點與x點連通,而且i點沒被訪問過{mark[ans]=i;m[i]=true;dfs(i,ans+1);m[i]=false;}return ; } int main() {//freopen("text.txt","r",stdin);//文件輸入int cnt=1;while(cin>>n){memset(map,0,sizeof(map));//一輪下來,有些數據要被重置int x=1,y=1;ans1=0;//重置while(true){cin>>x>>y;if(x==0||y==0)break;map[x][y]=map[y][x]=1;//構建矩陣地圖}cout<<"CASE "<<cnt++<<":"<<endl;dfs(1,1);cout<<"There are "<<ans1<<" routes from the firestation to streetcorner "<<n<<"."<<endl;}return 0; }


優化

  • 用回溯法預先找到能到達的路徑,記錄在bool fir[maxn]數組中。如果fir[i]=true,則說明該點能到達終點。
    //似乎優化后跑得更慢了
void check(int x) {fir[x]=true;for(int i=2;i<maxn;i++)if(map[x][i]&&!fir[i])check(i); } //還要每次用memset(fir,false,sizeof(fir));重置 //在dfs前調用check()函數 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的Firetruck(DFS+回溯)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。