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,則說明該點能到達終點。
//似乎優化后跑得更慢了
總結
以上是生活随笔為你收集整理的Firetruck(DFS+回溯)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 01迷宫(BFS+记忆)
- 下一篇: P1217 回文质数(打表)