i是二进制表示路径的数。例如:
i
=
(
1010
)
2
i=(1010)_2
i=(1010)2 ,就可以表示到了第2、第4两个点,没到第1、第3两个点。
状态转移方程 3.1.
f
[
i
,
j
]
=
m
i
n
{
f
[
i
−
p
o
i
n
t
(
j
)
]
+
s
[
j
]
[
k
]
∣
0
≤
k
<
n
}
f[i,j]=min\{f[i- point(j)]+s[j][k]|0\leq k<n\}
f[i,j]=min{f[i−point(j)]+s[j][k]∣0≤k<n} 3.2. 注意点1:i这条路径要包含j 3.3. 注意点2: i去掉j的这条路径要包含k
AC代码
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>usingnamespace std;constdouble INF =23333333333.0;constint N =17, M =1<< N;double s[N][N];//记录距离double mp[N][5];//读入输入double f[M][N];//dp数组int n;inlinedoubledis(double x1,double y1,double x2,double y2){double x = x1 - x2;double y = y1 - y2;returnsqrt(x*x + y * y);}intmain(){scanf("%d",&n);for(int i =1; i <= n;++i){
cin >> mp[i][0]>> mp[i][1];}for(int i =0; i < n;++i)for(int j = i +1; j <= n;++j){double tem =dis(mp[i][0], mp[i][1], mp[j][0], mp[j][1]);
s[i][j]= s[j][i]= tem;}
n++;//算上原点for(int i =0; i <=1<< n;++i){for(int j =0; j < n;++j)
f[i][j]= INF;}
f[1][0]=0.0;//原点初始化for(int i =0; i <(1<< n);++i)//枚举状态for(int j =0; j < n;++j)if((i >> j)&1)for(int k =0; k < n;++k)//上一个点为kif((i -(1<< j))>> k &1)
f[i][j]=min(f[i][j], f[i -(1<< j)][k]+ s[k][j]);double res = INF;int allin =(1<< n)-1;for(int i =1; i < n;++i)
res =min(res, f[allin][i]);printf("%.2f", res);return0;}