cogs 6. 线型网络

★★☆   输入文件:linec.in   输出文件:linec.out   简单对比
时间限制:1 s   内存限制:256 MB

【问题描述】

N(N<=20)台 PC 放在机房内,现在要求由你选定一台 PC,用共N1条网线从这台机器开始一台接一台地依次连接他们,最后接到哪个以及连接的顺序也是由你选定的,为了节省材料,网线都拉直。求最少需要一次性购买多长的网线。(说白了,就是找出 N 的一个排列 P1P2P3..PN 然后 P1>P2>P3>...>PN 找出 |P1P2|+|P2P3|+...+|PN1PN| 长度的最小值)

【输入格式】

第一行 N ,下面 N 行,每行分别为机器的坐标(x,y)(x100<=x,y<=100)

【输出格式】

最小的长度,保留两位小数。

【输入样例】

3
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 }
View Code

 

来了个弗洛伊德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 }
View Code

 

来了个模拟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  
View Code

 

看了题解,什么高深的算法(比如:模拟算法),用了个数位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 }
View Code

 

posted @ 2017-05-23 16:25  ioioioioioio  阅读(186)  评论(0编辑  收藏  举报