解析
考场时想多了,其实根本不用分阶段
一维状压 (DP) 就行了
可我没想清楚,加了个第几次去稳固一个点的阶段
然后时间就炸了!!!
(Code)
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
double f[1 << 19] , ans;
int n;
struct points{
int x , y , z;
}a[20];
struct node{
double a;
int b;
}d[20][20];
inline bool cmp(node x , node y){return x.a < y.a;}
inline double calc(points x , points y){
return sqrt(((double)x.x - y.x) * (x.x - y.x) + ((double)x.y - y.y) * (x.y - y.y));
}
inline double min(double x , double y){return x < y ? x : y;}
int main()
{
while (1)
{
scanf("%d" , &n);
if (n == 0) break;
for(register int i = 1; i <= n; i++) scanf("%d%d%d" , &a[i].x , &a[i].y , &a[i].z);
for(register int i = 0; i < (1 << n); i++) f[i] = (double)1e18;
for(register int i = 1; i < 1 << n; i++)
{
int bz = 1;
for(register int j = n - 1; j >= 0; j--)
if (((i >> j) & 1) && (a[j + 1].z != 1)){bz = 0; break;}
if (bz) f[i] = 0;
}
for(register int i = 1; i <= n; i++)
{
for(register int j = 1; j <= n; j++)
{
d[i][j].a = calc(a[i] , a[j]);
d[i][j].b = j;
}
sort(d[i] + 1 , d[i] + n + 1 , cmp);
}
int l = 0;
for(register int i = 1; i < 1 << n; i++)
{
int s = 0;
for(register int j = n - 1; j >= 0; j--)
if ((i >> j) & 1) s++;
if (s < 2 || f[i] == (double)1e18) continue;
for(register int j = n - 1; j >= 0; j--)
if (!((i >> j) & 1))
{
int o = 1 , oo = 2;
while (!(i & (1 << d[j + 1][o].b - 1)) && o <= n) o++;
oo = o + 1;
while (!(i & (1 << d[j + 1][oo].b - 1)) && oo <= n) oo++;
f[i | (1 << j)] = min(f[i | (1 << j)] , f[i] + d[j + 1][o].a + d[j + 1][oo].a);
}
}
ans = min((double)1e18 , f[(1 << n) - 1]);
if (ans == (double)1e18) printf("No Solution
");
else printf("%.6lf
" , ans);
}
}