海賊王之偉大航路

2021-09-26 09:56:09 字數 2132 閱讀 5844

題目鏈結

思路:基本狀壓dp

看題目知道此題求的是最短哈密頓路徑,也就是一條從1到n的經過所有點的最短路徑。

我們可以使用狀態壓縮,使用乙個二進位制數state代表一種狀態,state代表經過的所有點的集合。

例如state=1,代表只經過1號點。

state=3(二進位制為0011),代表經過1號點和2號點。

state=5(二進位制為0101),代表經過1號點和3號點。

state=6(二進位制為0110),代表經過2號點和3號點。

…我們設定dp[state][j]代表經過點的集合為state,並且最後乙個點為j號點。

由此推出狀態轉移方程為:dp[state][j] = min(dp[state - (1 memset

(dp,

0x3f

,sizeof dp)

;for

(int i =

1; i <= n; i++)//

for(

int state =

1; state <=(1

<; state++

) dp[state]

[j]= minj;}}

}在上面的**中的初始化部分,首先將所有狀態初始化為inf,因為要求的是最小值,所有初始化為最大值,避免產生干擾。

然後將所有只有乙個點的狀態初始化為0.

接下來就是狀態轉移方程,求最小值。

但是,這裡有問題,在遍歷 j 的時候,我的 j 是從第乙個點開始遍歷的,這將導致求出來的最短路徑可能不是從第乙個點開始的,這樣只能算出以最後乙個點結尾的最短路徑,而不能算出從第乙個點開始,以最後乙個點結尾的最短路徑。

例如:樣例1:

0 10 20 999

5 0 90 30

99 50 0 10

999 1 2 0

最後求出的結果為:2 -> 1 -> 3 -> 4,明顯看到不是以1號點開始。

核心**2:改進後

//init

memset

(dp,

0x3f

,sizeof dp)

;for

(int i =

1; i <= n; i++)//

for(

int state =

1; state <=(1

<; state++

) dp[state]

[j]= minj;}}

}

改進之處為: j 不再從1號點開始,而從2號點開始,如此一來,相當於所有1號點的入邊都被忽略了,只計算了1號點的出邊。這樣肯定只能從1號點開始。

最後附上ac**:

#include

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace std;

typedef

long

long ll;

typedef vector<

int> vec;

//#pragma gcc optimize(2)

static

int n;

static

int g[20]

[20];

static

int dp[

1<<20]

[20];

//dp[state][j] 經過的點集為state,最後乙個點為j

void

work

(void)//

for(

int state =

1; state <=(1

<; state++

) dp[state]

[j]= minj;}}

} cout << dp[(1

<][n]

<< endl;

}int

main()

}work()

;return0;

}

海賊王之偉大航路

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

百練4124 海賊王之偉大航路

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

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

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