DFS 簡單的剪枝和狀態壓縮 海賊王之偉大航路

2021-08-03 05:35:02 字數 2494 閱讀 9736

今天碰到了這樣一道題目,是乙個關於深搜的題目

總時間限制: 

1000ms 

記憶體限制: 

65536kb

描述

「我是要成為海賊王的男人!」,路飛一邊喊著這樣的口號,一邊和他的夥伴們一起踏上了偉大航路的艱險歷程。

路飛他們偉大航路行程的起點是羅格鎮,終點是拉夫德魯(那裡藏匿著「唯一的大秘寶」——one piece)。而航程中間,則是各式各樣的島嶼。

因為偉大航路上的氣候十分異常,所以來往任意兩個島嶼之間的時間差別很大,從a島到b島可能需要1天,而從b島到a島則可能需要1年。當然,任意兩個島之間的航行時間雖然差別很大,但都是已知的。

現在假設路飛一行從羅格鎮(起點)出發,遍歷偉大航路中間所有的島嶼(但是已經經過的島嶼不能再次經過),最後到達拉夫德魯(終點)。假設他們在島上不作任何的停留,請問,他們最少需要花費多少時間才能到達終點?

輸入輸入資料報含多行。

第一行包含乙個整數n(2 < n ≤ 16),代表偉大航路上一共有n個島嶼(包含起點的羅格鎮和終點的拉夫德魯)。其中,起點的編號為1,終點的編號為n。

之後的n行每一行包含n個整數,其中,第i(1 ≤ i ≤ n)行的第j(1 ≤ j ≤ n)個整數代表從第i個島嶼出發到第j個島嶼需要的時間t(0 < t < 10000)。第i行第i個整數為0。

輸出輸出為乙個整數,代表路飛一行從起點遍歷所有中間島嶼(不重複)之後到達終點所需要的最少的時間。

樣例輸入

樣例輸入1:

40 10 20 999

5 0 90 30

99 50 0 10

999 1 2 0

樣例輸入2:

50 18 13 98 8

89 0 45 78 43

22 38 0 96 12

68 19 29 0 52

95 83 21 24 0

樣例輸出

樣例輸出1:

100樣例輸出2:

137

提示

對於樣例輸入1:路飛選擇從起點島嶼1出發,依次經過島嶼3,島嶼2,最後到達終點島嶼4。花費時間為20+50+30=100。

對於樣例輸入2:可能的路徑及總時間為:

1,2,3,4,5: 18+45+96+52=211

1,2,4,3,5: 18+78+29+12=137

1,3,2,4,5: 13+38+78+52=181

1,3,4,2,5: 13+96+19+43=171

1,4,2,3,5: 98+19+45+12=174

1,4,3,2,5: 98+29+38+43=208

所以最短的時間花費為137

單純的列舉在n=16時需要14!次運算,一定會超時。

這個乍一看是乙個旅行商問題???但是後來仔細觀察加網上查詢發現通過深搜+剪枝就可以解決

這道題給我的啟發是狀態壓縮

這道題裡面的剪枝有兩個

比較複雜的剪枝, 當前的狀態之前已經查詢到了,而且之前到達當前狀態的時候所花費的時間比當前花費的時間要少,那麼也沒有必要繼續查詢了 具體看乙個陣列 location_state[local_position][state] 

這裡的local_position表示當前位於哪座城市 state則表示已經走了哪些城市

比如 5   1 2 3 5

5   3  1  2  5 這兩種情況下 state都是一樣的

這裡state用位運算來表示 比如第乙個城市走過了則把第一位變為1 所以第i個城市走過了  則有state+pow(2,i-1)來更新

具體可以看**,這道題的另乙個坑點在於必須要最後到達的城市是n,一開始我沒注意這個條件,以為只要走過所有的城市就可以,最後錯了

**如下

//#include "stdafx.h"

#include#include#include#includeusing namespace std;

int n;

int cost[20][20];

int sum = 0;

int min_money;

bool vis[20];

int land_state[20][1 << 17];

int min1(int x, int y)

void dfs(int cur_land, int readycost, int state)

if (readycost > min_money) return; //最簡單的剪枝, 當前花費已經比結果多了,就不走了

if (readycost < land_state[cur_land][state] || land_state[cur_land][state] == -1)

else return; //發現之前到達這個狀態的時候結果比現在好,就剪掉

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

}int main()

ACM 海賊王之偉大航路 深搜剪枝

我是要成為海賊王的男人!路飛他們偉大航路行程的起點是羅格鎮,終點是拉夫德魯 那裡藏匿著 唯一的大秘寶 one piece 而航程中間,則是各式各樣的島嶼。因為偉大航路上的氣候十分異常,所以來往任意兩個島嶼之間的時間差別很大,從a島到b島可能需要1天,而從b島到a島則可能需要1年。當然,任意兩個島之間...

ACM 海賊王之偉大航路 深搜剪枝

我是要成為海賊王的男人!路飛他們偉大航路行程的起點是羅格鎮,終點是拉夫德魯 那裡藏匿著 唯一的大秘寶 one piece 而航程中間,則是各式各樣的島嶼。因為偉大航路上的氣候十分異常,所以來往任意兩個島嶼之間的時間差別很大,從a島到b島可能需要1天,而從b島到a島則可能需要1年。當然,任意兩個島之間...

ACM 海賊王之偉大航路 深搜剪枝

我是要成為海賊王的男人!路飛他們偉大航路行程的起點是羅格鎮,終點是拉夫德魯 那裡藏匿著 唯一的大秘寶 one piece 而航程中間,則是各式各樣的島嶼。因為偉大航路上的氣候十分異常,所以來往任意兩個島嶼之間的時間差別很大,從a島到b島可能需要1天,而從b島到a島則可能需要1年。當然,任意兩個島之間...