cogs 6. 线型网络
★★☆ 输入文件:
时间限制:1 s 内存限制:256 MB
linec.in
输出文件:linec.out
简单对比时间限制:1 s 内存限制:256 MB
【问题描述】
有 N(N<=20)台 PC 放在机房内,现在要求由你选定一台 PC,用共N−1条网线从这台机器开始一台接一台地依次连接他们,最后接到哪个以及连接的顺序也是由你选定的,为了节省材料,网线都拉直。求最少需要一次性购买多长的网线。(说白了,就是找出 N 的一个排列 P1P2P3..PN 然后 P1−>P2−>P3−>...−>PN 找出 |P1P2|+|P2P3|+...+|PN−1PN| 长度的最小值)
【输入格式】
第一行 N ,下面 N 行,每行分别为机器的坐标(x,y)(x为实数−100<=x,y<=100)
【输出格式】
最小的长度,保留两位小数。
【输入样例】
3
0 0
1 1
1 -1
0 0
1 1
1 -1
【输出样例】
2.83
看到最短路,写了个spfa竟然死循环:
1 #include<iostream>
2 #include<cstdio>
3 #include<algorithm>
4 #include<cmath>
5 #include<cstring>
6 #include<string>
7 #include<queue>
8
9 using namespace std;
10 const int N=1010;
11 const int Maxn=999999;
12
13 int now=1;
14 int head[N];
15 double dis[N];
16 bool vis[21];
17 double Answer;
18 int n;
19
20 queue<int>q;
21
22 struct node{
23 int u,v,nxt;
24 double w;
25 }E[N];
26
27 struct NODE{
28 int x,y;
29 }D[21];
30
31 inline void read(int &x)
32 {
33 char c=getchar();
34 x=0;
35 while(c<'0'||c>'9')c=getchar();
36 while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
37 }
38
39 inline double W_(int xx,int yy)
40 {
41 return sqrt(pow(abs(D[xx].x-D[yy].x),2)+pow(abs(D[xx].y-D[yy].y),2));
42 }
43
44 inline void add(int u,int v,double w)
45 {
46 E[now].u=u;
47 E[now].v=v;
48 E[now].w=w;
49 E[now].nxt=head[u];
50 head[u]=now;
51 now++;
52 }
53
54 inline void spfa(int x)
55 {
56 for(int i=1;i<=n;i++)
57 vis[i]=0,dis[i]=Maxn;
58 vis[x]=1;
59 dis[x]=0;
60 q.push(x);
61 while(!q.empty())
62 {
63 int top=q.front();
64 q.pop();
65
66 for(int i=head[top];i!=-1;i=E[i].nxt)
67 {
68 int v=E[i].v;
69 double w=E[i].w;
70 if(dis[v]>dis[top]+w);
71 {
72 dis[v]=dis[top]+w;
73 if(!vis[v])
74 q.push(v);
75 }
76 }vis[top]=0;
77 }
78 for(int i=1;i<=n;i++)
79 {
80 Answer+=dis[i];
81 }
82 }
83
84 int main()
85 {
86 read(n);
87 for(int i=1;i<=n;i++)
88 head[i]=-1;
89
90 for(int i=1;i<=n;i++)
91 {
92 scanf("%d%d",&D[i].x,&D[i].y);
93 }
94 for(int i=1;i<n;i++)
95 for(int j=i+1;j<n;j++)
96 {
97 double W=W_(i,j);
98 add(i,j,W);
99 add(j,i,W);
100 }
101 for(int i=1;i<n;i++)
102 add(i,n,W_(i,n));
103
104 double Minanswer=-1;
105 for(int i=1;i<=n;i++)
106 {
107 Answer=0;
108 spfa(i);
109 Minanswer=min(Minanswer,Answer);
110 }
111
112 printf("%.2lf",Minanswer);
113 return 0;
114 }
来了个弗洛伊德10分:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<string> 7 8 using namespace std; 9 const int N=22; 10 const double maxn=99999; 11 12 double map[N][N]; 13 int n; 14 15 struct NODE{ 16 double x,y; 17 }D[21]; 18 19 inline void read(int &x) 20 { 21 char c=getchar(); 22 x=0; 23 while(c<'0'||c>'9')c=getchar(); 24 while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar(); 25 } 26 27 inline double W_(int xx,int yy) 28 { 29 return sqrt(pow(fabs(D[xx].x-D[yy].x),2)+pow(fabs(D[xx].y-D[yy].y),2)); 30 } 31 32 int main() 33 { 34 35 //freopen("linec.in","r",stdin); 36 //freopen("linec.out","w",stdout); 37 38 read(n); 39 40 for(int i=1;i<=n;i++) 41 scanf("%lf%lf",&D[i].x,&D[i].y); 42 for(int i=1;i<=n;i++) 43 for(int j=1;j<=n;j++) 44 map[i][j]=maxn; 45 46 for(int i=1;i<=n;i++) 47 for(int j=1;j<=n;j++) 48 { 49 if(i==j)map[i][j]=map[j][i]=0; 50 else map[i][j]=map[j][i]=W_(i,j); 51 } 52 53 for(int k=1;k<=n;k++) 54 for(int i=1;i<=n;i++) 55 for(int j=1;j<=n;j++) 56 map[i][j]=min(map[i][j],map[i][k]+map[k][j]); 57 58 double Min=999999; 59 for(int i=1;i<=n;i++) 60 { 61 double Answer=0; 62 for(int j=1;j<=n;j++) Answer+=map[i][j]; 63 Min=min(Min,Answer); 64 } 65 66 printf("%.2lf",Min); 67 68 }
来了个模拟10分:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 6 using namespace std; 7 const int N=21; 8 9 struct node{ 10 double x,y; 11 }E[N]; 12 13 struct Node{ 14 double x,y; 15 }EE[N]; 16 17 int main() 18 { 19 freopen("linec.in","r",stdin); 20 freopen("linec.out","w",stdout); 21 int n; 22 scanf("%d",&n); 23 for(int i=1;i<=n;i++) 24 { 25 scanf("%lf%lf",&E[i].x,&E[i].y); 26 EE[i].x=E[i].x; 27 } 28 double minn=999999,ans; 29 for(int i=1;i<=n;i++) 30 { 31 ans=0; 32 for(int j=1;j<=n;j++) 33 EE[j].y=E[j].y; 34 for(int j=1;j<=n;j++) 35 { 36 if(i==j) continue; 37 ans+=sqrt(pow(abs(EE[i].x-E[j].x),2)+pow(abs(EE[i].y-E[j].y),2)); 38 EE[i].x=E[j].x; 39 EE[i].y=E[j].y; 40 } 41 minn=min(minn,ans); 42 } 43 printf("%.2lf",ans); 44 } 45
看了题解,什么高深的算法(比如:模拟算法),用了个数位dp我还没看懂,虽然过了:
1 #include <cmath> 2 #include <cstdio> 3 //---------------------------------------------------- 4 inline double Min(double num1,double num2) 5 { 6 return num1<num2?num1:num2; 7 } 8 inline double sqr(double num1) 9 { 10 return num1*num1; 11 } 12 int n; 13 int i,j,k; 14 int num1[1050000]; 15 16 double x[30],y[30]; 17 double dis[30][30]; 18 19 double dai,cache=99999999; 20 double ans[1050000][21]; 21 int main( ) 22 { 23 freopen( "linec.in" , "r" , stdin ); 24 freopen( "linec.out" , "w" , stdout ); 25 scanf("%d",&n); 26 for (i=1; i<=n; i++) 27 { 28 scanf("%lf%lf",&x[i],&y[i]); 29 for (j=1; j<i; j++) 30 { 31 dis[i][j]= 32 dis[j][i]=sqrt( sqr(x[i]-x[j]) + sqr(y[i]-y[j]) ); 33 } 34 } 35 for (i=0; i<=n; i++) num1[1<<i]=i+1; 36 for (i=1; i< 1<<n; i++) if (!num1[i]) 37 for (j=i; j; j-=j&-j) 38 { //j枚举状态i的每一个1,标记当前终点 39 ans[i][num1[j&-j]]=99999999; 40 //更新目标: ans[i][num1[j&-j]] 41 for (k=i-(j&-j); k; k-=(k&-k)) // 枚举上一个位置 42 if (ans[i][num1[j&-j]] > ans[i-(j&-j)][num1[k&-k]] + dis[num1[j&-j]][num1[k&-k]]) 43 ans[i][num1[j&-j]] = ans[i-(j&-j)][num1[k&-k]] + dis[num1[j&-j]][num1[k&-k]]; 44 //更新来源:ans[i-j&-j][num1[k&-k]] 45 } 46 for (i=1; i<=n; i++) 47 cache=Min(cache,ans[(1<<n)-1][i]); 48 printf("%.2f",cache); 49 }