[最短路] [luoguP1027] Car的旅行路线

Car的旅行路线

题目描述

又到暑假了,住在城市A的Car想和朋友一起去城市B旅游。她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一条笔直的高速铁路,第I个城市中高速铁路了的单位里程价格为Ti,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为t。

   那么Car应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。

找出一条从城市A到B的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。

输入输出格式

输入格式:

第一行为一个正整数n(0<=n<=10),表示有n组测试数据。

每组的第一行有四个正整数s,t,A,B。

S(0<S<=100)表示城市的个数,t表示飞机单位里程的价格,A,B分别为城市A,B的序号,(1<=A,B<=S)。

接下来有S行,其中第I行均有7个正整数xi1,yi1,xi2,yi2,xi3,yi3,Ti,这当中的(xi1,yi1),(xi2,yi2),(xi3,yi3)分别是第I个城市中任意三个机场的坐标,T I为第I个城市高速铁路单位里程的价格。

 

输出格式:

共有n行,每行一个数据对应测试数据。 保留一位小数

 

俺的题解

向量求第四点+SPFA

本人求第四点的方式好像有点麻烦= =

  先用向量求出三个点中的直角点,然后通过确定位置后的三点坐标计算第四点。

                              

                     图中A3为直角点,x4=x1+x2-x3    y4=y1+y2-y3

 

存边比较巧妙。每个机场占一个点,于是每个城市占了4个位置。直接暴力循环把火车和飞机的边一块存了...

从起点城市的4个机场分别SPFA,共4次。取终点城市4个机场的最小值即为答案。

俺的代码

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<queue>
  5 #include<cmath>
  6 #include<vector>
  7 using namespace std;
  8 #define INF 1000000000.0
  9 int tt,s,t,a,b;
 10 int prize[170];
 11 double d[20000];
 12 struct cc
 13 {
 14     int x,y,p;
 15 }city[170][5];
 16 struct vec
 17 {
 18     int x,y;
 19     int p,q; 
 20 };
 21 struct node
 22 {
 23     int v;
 24     double w;
 25 };
 26 vector<node> edge[20000];
 27 int count(int k)//求第四点 
 28 {
 29     int c=0;vec v[5];
 30     for(int i=1;i<3;i++)
 31     {
 32         for(int j=i+1;j<=3;j++)
 33         {
 34             c++;
 35             v[c].x=city[k][i].x-city[k][j].x;
 36             v[c].y=city[k][i].y-city[k][j].y;
 37             v[c].p=i;
 38             v[c].q=j;
 39         }
 40     } 
 41     bool sol=0;
 42     for(int i=1;i<c;i++)
 43     {
 44         for(int j=i+1;j<=c;j++)
 45         {
 46             if((v[i].x*v[j].x)+(v[i].y*v[j].y) == 0)
 47             {
 48                 int wei[5]={0},zu=0;
 49                 wei[v[i].p]++;wei[v[i].q]++;
 50                 wei[v[j].p]++;wei[v[j].q]++;
 51                 int oth[2]={0},cc=0;
 52                 for(int w=1;w<=3;w++){
 53                     if(wei[w] == 2)
 54                         zu=w;
 55                     else
 56                         oth[++cc]=w;
 57                 }
 58                 if(city[k][oth[1]].x  > city[k][oth[2]].x ||(city[k][oth[1]].x  == city[k][oth[2]].x && city[k][oth[1]].y  > city[k][oth[2]].y ))
 59                 {
 60                     int temp=oth[2];
 61                     oth[2]=oth[1];
 62                     oth[1]=temp;
 63                 }
 64 
 65                 city[k][4].x=city[k][oth[1]].x+city[k][oth[2]].x-city[k][zu].x;
 66                 city[k][4].y=city[k][oth[1]].y+city[k][oth[2]].y-city[k][zu].y;
 67                 sol=1;
 68                 break;
 69             }
 70         }
 71         if(sol==1)break;
 72     }
 73 }
 74 
 75 double countdis(int i,int n1,int j,int n2)
 76 {
 77     return sqrt((city[i][n1].x-city[j][n2].x)*(city[i][n1].x-city[j][n2].x)
 78                +(city[i][n1].y-city[j][n2].y)*(city[i][n1].y-city[j][n2].y));
 79 }
 80 void SPFA(int a)
 81 {
 82     for(int i=0;i<=4*s+1;i++)
 83     {
 84         d[i]=INF;
 85     }
 86     queue<int>q;
 87     q.push(a);
 88     d[a]=0.0;
 89     while(!q.empty())
 90     {
 91         int x=q.front();q.pop();
 92         for(int i=0;i<edge[x].size();i++)
 93         {
 94             int v=edge[x][i].v;
 95             double w=edge[x][i].w;
 96             if(d[x]+w < d[v])
 97             {
 98                 d[v]=d[x]+w;
 99                 q.push(v);
100             }
101         }
102     }
103 }
104 int main()
105 {
106     scanf("%d",&tt);
107     while(tt--)
108     {
109     scanf("%d%d%d%d",&s,&t,&a,&b);
110     for(int i=1;i<=s;i++)
111     {
112         for(int j=1;j<=3;j++)
113         {
114             int x,y;scanf("%d%d",&x,&y);
115             city[i][j].x=x;
116             city[i][j].y=y;
117         }
118         count(i);
119         scanf("%d",&prize[i]);
120     }
121 
122     for(int i=1;i<=s;i++)
123     {
124         for(int k1=1;k1<=4;k1++)
125         {
126             for(int j=1;j<=s;j++)
127             {
128                 for(int k2=1;k2<=4;k2++)
129                 {
130                     if(i == j && k1 < k2)
131                     {
132                         node p;
133                         p.v=(j-1)*4+k2;
134                         p.w=countdis(i,k1,j,k2)*prize[i];
135                         edge[(i-1)*4+k1].push_back(p);
136                         node q;
137                         q.v=(i-1)*4+k1;
138                         q.w=p.w;
139                         edge[(j-1)*4+k2].push_back(q);
140                     }
141                     if(i != j)
142                     {
143                         node p;
144                         p.v=(j-1)*4+k2;
145                         p.w=countdis(i,k1,j,k2)*t;
146                         edge[(i-1)*4+k1].push_back(p);
147                         node q;
148                         q.v=(i-1)*4+k1;
149                         q.w=p.w;
150                         edge[(j-1)*4+k2].push_back(q);
151                     }
152                 }
153             }
154         }
155     }
156     double ans=1000000000.0;
157     for(int i=1;i<=4;i++)
158     {
159         SPFA((a-1)*4+i);
160         for(int j=1;j<=4;j++)
161         {
162             ans=min(ans,d[(b-1)*4+j]);
163         }
164     }
165     printf("%.1lf\n",ans);
166     }
167     return 0;
168 }
点击查看

 

俺的反思

注意是无向边,可能只有我会犯这么sb的错误= =

posted @ 2017-08-05 19:39  秃猴  阅读(269)  评论(0编辑  收藏  举报