深度優先搜尋的幾道題目

2021-09-24 04:31:00 字數 4693 閱讀 5773

感覺還是比動規簡單一些的……但是最近腦子有點糊。

首先是要注意鄰接表是有兩種的,在稀疏圖中,最好用vector存每個頂點的邊的資訊,而不是稠密圖中的g[x][y]。

第二是步數最少的路徑……存path然後把path拷貝到bestpath……要不然會亂。我犯了很多次傻然後後面debug。這個錯誤很蠢但是我一開始也沒想清楚。

下面是一些具體問題。

百練2815 城堡問題

基本上可以算乙個連通圖的模板題了。但是有幾個點。首先是如何統計房間的數量?我反正是沒想到,把不同的房間用不同的數字染色。統計顏色的數量就好了。然後就是把visited返回要放在dfs外面……要不然邏輯上有問題,我也是蠢了。

最後ac**:

//百練2815:城堡問題

#include #include using namespace std;

const int maxm = 51;

int dx = ;

int dy = ;

int visited[maxm][maxm];

int m, n;

int map[maxm][maxm];

int legal(int x, int y)

int roomnum;

int maxroomsize;

int cursize;

int dfs(int x, int y)

return 1;

}int main()

} int init = 1;

for (int i = 0; i < m; ++i)

} cout << roomnum << endl;

cout << maxroomsize << endl;

return 0;

}

或者下面這種:

//百練2815:城堡問題

#include #include using namespace std;

const int maxm = 51;

int dx = ;

int dy = ;

int visited[maxm][maxm];

int m, n;

int map[maxm][maxm];

int legal(int x, int y)

int roomnum;

int maxroomsize;

int cursize;

int dfs(int x, int y, int & cursize)

maxroomsize = max(maxroomsize, cursize);

return 1;

}int main()

} int init = 1;

for (int i = 0; i < m; ++i)

} cout << roomnum << endl;

cout << maxroomsize << endl;

return 0;

}

百練1724 roads

我其實看了課件才有思路的……好吧。就是要把cost拿出來作為一維度存中間結果。

這個題就是注意道路不止一條,所以要用vector存,不能用鄰接矩陣。

另外值得一提的是有乙個剪枝會導致wa。就是如果下乙個目的地不是n而道路的花費加上已經有的花費等於k的時候剪枝。這個是錯的因為有可能某條路花銷為0.

還有就是我嘗試用動規做,也就是「我為人人」,狀態轉移方程為:

minlength[roadinfo[i][j].dest][cost] = min(minlength[roadinfo[i][j].dest][cost], minlength[i][k] + roadinfo[i][j].length)
但是實際上是不行的。因為要考慮到回頭路的存在,因此搜尋順序就成了個問題,因為現在就不能從i=1搜到i=n了。

最後ac**:

#include #include #include #include using namespace std;

const int maxn = 102;

const int maxk = 10002;

const int maxr = 10002;

const int inf = (1 << 30);

int n, k, r;

struct road;

vector roadinfo[maxn][maxn];

//int roadinfo[maxn][maxn][2];

int minlength[maxn][maxk];

int output = inf;

int visited[maxn];

int dfs(int location, int cost, int curlength)

} for (int i = 2; i <= n; ++i)

} }return 0;

}int main()

for (int i = 0; i < maxn; ++i)

} minlength[1][0] = 0;

visited[1] = 1;

dfs(1, 0, 0);

cout << (output == inf? -1: output) << endl;

return 0;

}

其實寫得有點囉嗦……

百練1190 生日蛋糕

這個是例題,主要的啟示是可行性剪枝的預見性。還有搜尋順序從大到小,從下往上,便於可行性剪枝(這讓我想起聚類和動規……自底向上好像都比自頂向下要效率高?應該這樣可以排掉大量的可能性)。另外這個題目有很多細節上的處理要注意的。

首先是蛋糕的表面積,包括所有層的頂部露在外面的面積和側面積,而前一部分直接就等於最底層的底面積。而且注意不要忘了加。

另外是從底層最大高度和半徑開始列舉,設定的是int,注意這個是捨去小數部分的,因此要+1再開始列舉。

最後是還有乙個可以改進的地方是記憶化搜尋。

最後的ac**(抄講義的(捂臉)):

#include #include #include const int maxn = 10000, maxm = 20;

int n, m;

int minv[maxm+1];

int mina[maxm+1];

int maxv[maxm+1][30][30];

int minarea = 0xffffff;

int area;

int calmaxv(int curdepth, int r, int h)

maxv[curdepth][r][h] = v;

return v; }}

int dfs(int curdepth, int remv, int maxr, int maxh)

else return 0;

} if (minv[curdepth-1] > remv) return 0;

if (mina[curdepth-1] + area >= minarea) return 0;

if (calmaxv(curdepth, maxr, maxh) < remv) return 2;

//printf("escape return\n");

for (int r = maxr; r >= curdepth; --r)

else area -= 2 * r * h;

} }return 0;

}int main()

if (minv[m] > n) printf("0\n");

else

return 0;

}

海賊王之偉大航路

這個其實是生日蛋糕的變式題。那個可行性剪枝(就那個蛋糕裡面最強的剪枝)我沒想到,一開始想的乙個作死的o(n^2)版本,試了好幾次才幡然醒悟自己的愚蠢……這其實有點像啟發式函式。最後我採取的策略是記錄所有 的道路cost裡面最小的那個,然後如果已經有的pathcost加上(n-depth)*mincost比最優解大就捨掉,事實證明儘管這個啟發式函式相比蛋糕裡面的相當之不靠譜,但是還是非常有用的。

最後ac**:

#include #include #include using namespace std;

int minpath = 0xffffff;

bitset<16> vstd;

int n;

int minr = 0xffffff;

int route[16][16];

int dfs(int location, int path, int depth)

vstd[location] = 1;

if (path >= minpath)

for (int i = 1; i < n; ++i)

vstd[location] = 0;

return 0;

}int main()

} dfs(0, 0, 0);

printf("%d\n", minpath);

return 0;

}

(本來一開始還想嘗試a搜尋然後失敗了,事實證明根本不懂a演算法(捂臉),考完有空研究一下)

先這些吧。

深度優先搜尋經典題目

michael喜歡滑雪百這並不奇怪,因為滑雪的確很刺激。可是為了獲得速度,滑的區域必須向下傾斜,而且當你滑到坡底,你不得不再次走上坡或者等待公升降機來載你。michael想知道載乙個區域中最長的滑坡。區域由乙個二維陣列給出。陣列的每個數字代表點的高度。下面是乙個例子 1 2 3 4 5 16 17 ...

廣度優先搜尋 深度優先搜尋

前言 這幾天複習圖論演算法,覺得bfs和dfs挺重要的,而且應用比較多,故記錄一下。廣度優先搜尋 有乙個有向圖如圖a 圖a廣度優先搜尋的策略是 從起始點開始遍歷其鄰接的節點,由此向外不斷擴散。1.假設我們以頂點0為原點進行搜尋,首先確定鄰接0的頂點集合s0 2.然後確定頂點1的集合s1 頂點2沒有鄰...

廣度優先搜尋,深度優先搜尋

深度優先搜尋 depth first search 簡稱dfs。最直觀的例子就是 走迷宮 廣度優先搜尋 每個頂點都要進出一遍佇列,每個邊也都會被訪問一次,所以 時間複雜度o v e 主要消耗記憶體的是visited prev陣列 queue佇列,所以 空間複雜度o v 深度優先搜尋 每條邊最多會被訪...