題目鏈結
思路:基本狀壓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年。當然,任意兩個島之間...