状态定义
d
p
[
i
]
[
S
]
=
最终到达第
i
个
t
o
w
n
,经过的
t
o
w
n
状态为
S
的最短时间
dp[i][S] = 最终到达第 i 个town,经过的town状态为 S 的最短时间
dp[i][S]=最终到达第i个town,经过的town状态为S的最短时间
状态转移
d
p
[
i
]
[
S
]
=
m
i
n
(
d
p
[
j
]
[
S
−
2
i
]
+
t
i
m
e
(
i
,
j
)
)
,
S
>
>
i
&
1
=
1
a
n
d
S
>
>
j
&
1
=
1
dp[i][S] = min(dp[j][S - 2^i] + time(i, j)~), ~~S >> i ~\& ~ 1 = 1 ~and~S >> j ~\& ~ 1 = 1
dp[i][S]=min(dp[j][S−2i]+time(i,j)),S>>i&1=1andS>>j&1=1
a
n
s
=
m
i
n
(
d
p
[
i
]
[
S
]
+
t
i
m
e
(
i
,
0
)
)
ans = min(dp[i][S] + time(i, 0)~)
ans=min(dp[i][S]+time(i,0))
时间复杂度
O
(
2
n
n
2
)
O(2^nn^2)
O(2nn2)
Hard version 可以把chest也看作town, 最终可以不经过chest回到原点,但是town点必须全部经过。
Code
double dp[20][140000];
pii s[20];intmain(){
IOS;int n, m; cin >> n >> m;for(int i =0; i < n + m; i++) cin >> s[i].ft >> s[i].sd;for(int i =0; i < n + m; i++)for(int j =0; j <1<< n + m; j++)
dp[i][j]=1e18;for(int i =0; i < n + m; i++)
dp[i][1<< i]=hypot(s[i].ft, s[i].sd);for(int k =1; k <1<< n + m; k++){int v =1<<__builtin_popcount(k >> n);for(int i =0; i < n + m; i++)if(k &1<< i)for(int j =0; j < n + m; j++)if(k &1<< j){double time =hypot(s[i].ft - s[j].ft, s[i].sd - s[j].sd)/ v;if(i >= n) time *=2;
dp[i][k]=min(dp[i][k], dp[j][k -(1<< i)]+ time);}}double ans =1e18;for(int i =0; i < n + m; i++)for(int j =(1<< n)-1; j <1<< n + m; j +=1<< n)if(j &1<< i){int v =1<<__builtin_popcount(j >> n);double last_time =hypot(s[i].ft, s[i].sd)/ v;
ans =min(ans, dp[i][j]+ last_time);}
cout << fixed <<setprecision(8)<< ans << endl;return0;}