description
给定(n)个点,有若干个是初始固定的.一个点是固定的,当且仅当它初始固定或与至少两个固定点间连边.连接一条边的代价为此边长,求将所有点固定的最小代价.
solution
根据该数据规模,不难看出是状压题.我们先确定状态,这里规定状态中(1)为已固定的点,那么可以从小到大枚举状态,利用刷表法,直接贪心转移即可.
code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define R register
#define next MabLcdG
#define mod 1
#define debug puts("mlg")
#define Mod(x) ((x%mod+mod)%mod)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
inline ll read();
inline void write(ll x);
inline void writesp(ll x);
inline void writeln(ll x);
inline double Sqrt(double x){
double l=0,r=100000000.0;
while(l+0.0000000000001<r){
double mid=(l+r)/2;
if(mid*mid<x) l=mid+0.0000000000001;
else r=mid;
}
return l;
}
ll n;
double f[(1<<19)];
ll tot;
struct node{
ll x,y;
bool check;
inline void init(){
x=read(),y=read();check=read();
}
}v[20];
inline double calc(ll i,ll j){
return sqrt(1.0*(v[i].x-v[j].x)*(v[i].x-v[j].x)+1.0*(v[i].y-v[j].y)*(v[i].y-v[j].y));
}
struct Dode{
double dis;
ll p;
inline void Init(ll i,ll j){
dis=calc(i,j);p=j;
}
bool operator <(Dode X)const{return dis<X.dis;}
}c[20][20];
ll h;
int main(){
while(n=read()){
h=0;tot=0;
for(R ll i=1;i<=n;i++) v[i].init(),tot+=(v[i].check?(1<<i-1):0),h+=(v[i].check?1:0);
for(R ll i=1;i<=n;i++){
for(R ll j=1;j<=n;j++) c[i][j].Init(i,j);
sort(c[i]+1,c[i]+n+1);
}
if(h==n){
puts("0.000000");
continue;
}
if(h<2){
puts("No Solution");
continue;
}
memset(f,127,sizeof f);
double Maxn=f[0];f[tot]=0;
for(R ll i=tot;i<(1<<n);i++){
if(f[i]==Maxn) continue;
for(R ll j=1;j<=n;j++){
if((i&(1<<j-1))) continue;
ll cnt=0;double dis=0;
for(R ll k=1;k<=n;k++){
if((i&(1<<c[j][k].p-1))) ++cnt,dis+=c[j][k].dis;
// if(cnt==2)printf("%.6lfa
",dis);
if(cnt==2){
f[i+(1<<(j-1))]=min(f[i+(1<<(j-1))],f[i]+dis);
break;
}
}
}
}
printf("%.6lf
",f[(1<<n)-1]);
}
}
inline ll read(){ll x=0,t=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') t=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*t;}
inline void write(ll x){if(x<0){putchar('-');x=-x;}if(x<=9){putchar(x+'0');return;}write(x/10);putchar(x%10+'0');}
inline void writesp(ll x){write(x);putchar(' ');}
inline void writeln(ll x){write(x);putchar('
');}