1344 线型网络
题目描述 Description
有 N ( <=20 ) 台 PC 放在机房内,现在要求由你选定一台 PC,用共 N-1 条网线从这台机器开始一台接一台地依次连接他们,最后接到哪个以及连接的顺序也是由你选定的,为了节省材料,网线都拉直。求最少需要一次性购买多长的网线。(说白了,就是找出 N 的一个排列 P1 P2 P3 ..PN 然后 P1 -> P2 -> P3 -> ... -> PN 找出 |P1P2|+|P2P3|+...+|PN-1PN| 长度的最小值)
输入描述 Input Description
第一行 N ,下面 N 行,每行分别为机器的坐标(x,y) ( 实数 -100<=x,y<=100 )
输出描述 Output Description
最小的长度,保留两位小数。
样例输入 Sample Input
3
0 0
1 1
1 -1
样例输出 Sample Output
2.83
数据范围及提示 Data Size & Hint
一上来,没思考,mst,样例过来,然后就过了一个点
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define b(i) i*i #define N 31 struct node{ int x,y; }a[N]; struct ss{ int x,y; double val; bool operator < (const ss &t)const{return val<t.val;} }e[N*N]; int n,cnt,fa[N]; inline double run(node p,node q){ return sqrt(b(p.x-q.x)+b(p.y-q.y)); } int find(int x){ return fa[x]==x?x:fa[x]=find(fa[x]); } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(i==j) continue; e[++cnt].x=i;e[cnt].y=j; int tmp=(a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y); e[cnt].val=sqrt(tmp); } } //for(int i=1;i<=cnt;i++) printf("%d %d %.2lf\n",e[i].x,e[i].y,e[i].val); sort(e+1,e+cnt+1); int k=0;double ans=0; for(int i=1;i<=cnt;i++){ int fx=find(e[i].x),fy=find(e[i].y); if(fx!=fy){ fa[fx]=fy; ans+=e[i].val; if(++k==n-1) break; } } printf("%.2lf\n",ans); return 0; }
附上第一个WA点
看了题解:
此人太懒,大量随机数验证。和费马斯小定理如出一辙。倒是也省了dfs
AC代码:
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<ctime> #include<iostream> using namespace std; #define N 21 int n,a[N]; double x[N],y[N],dis[N][N]; inline double run(double a,double b){ return sqrt(a*a+b*b); } inline double len(int i,int j){ return a[i]<a[j]?dis[a[i]][a[j]]:dis[a[j]][a[i]]; } int main(){ srand(time(0)); ios::sync_with_stdio(0); cin>>n; for(int i=0;i<n;i++){ cin>>x[i]>>y[i]; for(int j=0;j<i;j++){ dis[j][i]=run(x[i]-x[j],y[i]-y[j]); } } double ans=0x7fffffff,tmp=0; for(int t=0;t<10000;t++){ for(int i=0;i<n;i++) a[i]=i; for(int i=0;i<n;i++){ int j=rand()%(n-i)+i; if(i==j) continue; swap(a[i],a[j]); } bool flag=1; for(;flag;){ flag=0; for(int i=2;i<n-1;i++){ for(int j=1;j<i;j++){ if(len(j-1,j)+len(i,i+1)>len(j-1,i)+len(j,i+1)){ while(i>j){ swap(a[i],a[j]); i--;j++; } flag=1; break; } } if(flag) break; } } tmp=0; for(int i=1;i<n;i++) tmp+=len(i,i-1); ans=min(ans,tmp); } cout.precision(2); cout.setf(ios::fixed); cout<<ans<<endl; return 0; }