首页 > 代码库 > [NOIP2001]Car的旅行路线

[NOIP2001]Car的旅行路线

题目描述 Description

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

那么Car应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。
任务
找出一条从城市A到B的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。

输入描述 Input Description

第一行为一个正整数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个城市高速铁路单位里程的价格。

输出描述 Output Description

共有n行,每行一个数据对应测试数据。

样例输入 Sample Input

1
3 10 1 3
1 1 1 3 3 1 30
2 5 7 4 5 2 1
8 6 8 8 11 6 3

样例输出 Sample Output

47.5

分析

最短路的裸题= = 唯一存在的问题就是如何把“四源四终点”的最短路问题转化为复杂度较低的问题。借用刘汝佳《训练指南》上网络流建模的思路,这里不妨建立一个虚拟机场0,在0和城市A的四个机场各连一条权值为0的边,即可用单源最短路算法求解。另。。因为题目中边数E很接近n2,所以用Dijkstra会比SPFA快很多(2s和4s)。。。。别看我,我是写完SPFA之后才想起来的=_=||

 

 1 //Awsm.Definer →_→
 2 //E-Mail: willywu1998@foxmail.com
 3 #include <cstdio>
 4 #include <deque>
 5 #include <cmath>
 6 #include <memory.h>
 7 #include <iostream>
 8 #define MAX 0x3f3f3f3f
 9 #define mod(x) ( sqrt((x) * (x)) )
10 using namespace std;
11 struct v { //vector(location)
12     int x,y;
13     v (){};v(int a,int b):x(a),y(b){};
14     v operator +(const v& b) {return v(x+b.x,y+b.y);}
15     v operator -(const v& b) {return v(x-b.x,y-b.y);}
16     int operator * (const v& b) {return x*b.x + y*b.y;}
17 };
18 inline v get4(v &p1,v &p2,v &p3) {
19     if((p2 - p1) * (p3 - p1) == 0return p2 - p1 + p3;
20     if((p1 - p2) * (p3 - p2) == 0return p1 - p2 + p3;
21     return p1 - p3 + p2;
22 }
23 inline void getv(v &k) {
24     scanf("%d%d",&k.x,&k.y);
25 }
26 int n,s,t,A,B; //the meaning of s will be changed in function "work"...
27 double dis[404][404]={0};
28 inline void makegragh() { //build dis[][]
29     v p[404];
30     int Ti;
31     for(int i=1;i<=s;i+=4) {
32         getv(p[i]),getv(p[i+1]),getv(p[i+2]);scanf("%d",&Ti);
33         p[i+3]=get4(p[i],p[i+1],p[i+2]);
34         for(int j=0;j<3;++j)for(int k=j;k<4;++k)
35             dis[i+j][i+k]=dis[i+k][i+j]=Ti * mod((p[i+k]-p[i+j]));
36         for(int j=1;j<i;++j)for(int k=0;k<4;++k)
37             dis[j][i+k]=dis[i+k][j]=t * mod((p[i+k]-p[j]));
38     }
39 }
40 inline double SPFA() { 
41     deque <int> Q;
42     int k = 4 * A - 3,K = 4 * B - 3;
43     Q.push_front(k),Q.push_front(k+1),Q.push_front(k+2),Q.push_front(k+3);
44     bool in_Q[404] = {0};in_Q[k]=in_Q[k+1]=in_Q[k+2]=in_Q[k+3]=1;
45     double cost[404];
46     int i,t;
47     for(i=1;i<=s;++i) cost[i] = MAX;
48     cost[k]=cost[k+1]=cost[k+2]=cost[k+3]=0;
49     while(!Q.empty()) {
50         t = Q.front(); Q.pop_front(); in_Q[t] = 0;
51         for(i = 1;i <= s;++i) {
52             if(i==t)continue;
53             if(cost[i] > cost[t] + dis[i][t]) { //relax
54                 cost[i] = cost[t] + dis[i][t];
55                 if(in_Q[i])continue;
56                 if(Q.empty() || cost[Q.front()] < cost[i])Q.push_back(i);
57                 else Q.push_front(i);
58                 in_Q[i] = 1;
59             }
60         }
61     }
62     return min(min(cost[K],cost[K+1]),min(cost[K+2],cost[K+3]));
63 }
64 void work() {
65     scanf("%d%d%d%d",&s,&t,&A,&B);s *= 4;//s -> sum of airports
66     makegragh();
67     printf("%.1f\n", SPFA()); //(0) -> (4*n+1)
68 }
69 int main(){
70     #ifdef DEBUG
71     freopen("test.in","r",stdin);
72     #endif
73     scanf("%d",&n);
74     while(n--)
75         work();
76     return 0;
77 }