标签:ora 解析 小数 cstring sqrt can tail badge 保留
又到暑假了,住在城市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行,每行一个数据对应测试数据。 保留一位小数
题目解析:
这是一道比较裸的最短路问题,首先是建图问题,题目只给了一个城市三个点的坐标,设已知三点坐标为(x1,y1) (x2,y2) (x3,y3),如何求(x4,y4)?
因为这是一个垂直,我们可以想到勾股,向量等方法,但不简便。由于这是个矩形,不难想到对角线中点相等,那么已知的三个点哪两个是对角的点呢?
我们可以通过勾股定理求出三条边,根据边越大,角越大的规则可以求出直角,设为(x3,y3),不难得出:x4=x2+x3-x1;y4=y2+y3-y1;
这样整个图的所有点求出,开始建图。而由于这是个稠密图,我们建议用邻接矩阵(手残用了邻接表)。
从主观上看,我们可以以a城市的四个机场为起点,这样需要跑四次spfa。但是我们可以利用虚点的思想,问题可以转化为从虚点出发到B城市的spfa。
(假设有一个点:0,它到四个起点的dist==0)
而程序中并不需要把虚点建出来连边,只需把四个起点的dist设为0即可;
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #define maxn 10001 7 using namespace std; 8 int n,s,a,b,u[maxn],v[maxn],fr[maxn],cure,curn,frst[maxn],nst[maxn],que[maxn],head,tail,vis[maxn],T,t[maxn],des,xx[maxn],yy[maxn]; 9 //int ans=0x7ffffff; 10 float w[maxn],dist[maxn]; 11 int min(int x,int y) 12 { 13 return x>y?y:x; 14 } 15 void add(int x,int y,float z) 16 { 17 u[cure++]=x;v[cure]=y,w[cure]=z; 18 nst[cure]=frst[x];frst[x]=cure; 19 } 20 float dis(int x1,int y1,int x2,int y2) 21 { 22 float ans=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); 23 return ans; 24 } 25 int main() 26 { 27 scanf("%d",&n); 28 for(int timm=1;timm<=n;timm++) 29 { 30 memset(frst,-1,sizeof(frst)); 31 memset(nst,-1,sizeof(nst)); 32 memset(u,0,sizeof(u)); 33 memset(v,0,sizeof(v)); 34 memset(t,0,sizeof(t)); 35 memset(w,0,sizeof(w)); 36 memset(que,0,sizeof(que)); 37 memset(vis,0,sizeof(vis)); 38 memset(fr,0,sizeof(fr)); 39 memset(xx,0,sizeof(xx)); 40 memset(yy,0,sizeof(yy)); 41 curn=0;cure=0; 42 head=tail=0; 43 scanf("%d%d%d%d",&s,&T,&a,&b); 44 for(int i=1;i<=s;i++) 45 { 46 int x1,y1,x2,y2,x3,y3,x4,y4,nodex,nodey; 47 float e1,e2,e3; 48 scanf("%d%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&x3,&y3,&t[i]); 49 e1=dis(x2,y2,x3,y3); 50 e2=dis(x1,y1,x3,y3); 51 e3=dis(x1,y1,x2,y2); 52 if(e1>e2&&e1>e3) 53 { 54 x4=x2+x3-x1;y4=y2+y3-y1; 55 } 56 else if(e2>e1&&e2>e3) 57 { 58 x4=x1+x3-x2;y4=y1+y3-y2; 59 } 60 else if(e3>e1&&e3>e2) 61 { 62 x4=x1+x2-x3;y4=y1+y2-y3; 63 } 64 xx[++curn]=x1;yy[curn]=y1;fr[curn]=i; 65 xx[++curn]=x2;yy[curn]=y2;fr[curn]=i; 66 xx[++curn]=x3;yy[curn]=y3;fr[curn]=i; 67 xx[++curn]=x4;yy[curn]=y4;fr[curn]=i; 68 } 69 for(int j=1;j<=curn;j++) 70 for(int k=1;k<=curn;k++) 71 { 72 if(j==k) 73 continue; 74 if(fr[j]==fr[k]) 75 { 76 if(fr[j]==a||fr[j]==b) 77 { 78 add(j,k,0); 79 if(fr[j]==b) 80 des=j; 81 } 82 else 83 { 84 float fee=dis(xx[j],yy[j],xx[k],yy[k])*t[fr[j]]; 85 add(j,k,fee); 86 } 87 } 88 else 89 { 90 float fee=dis(xx[j],yy[j],xx[k],yy[k])*T; 91 add(j,k,fee); 92 } 93 } 94 for(int j=1;j<=curn;j++) 95 { 96 dist[j]=0x7fffffff; 97 if(fr[j]==a) 98 { 99 dist[j]=0; 100 que[tail]=j; 101 } 102 } 103 tail++; 104 while(head<tail) 105 { 106 int node=que[head]; 107 head++; 108 if(fr[node]!=a) vis[node]=0; 109 for(int ed=frst[node];ed!=-1;ed=nst[ed]) 110 { 111 int to=v[ed]; 112 if(dist[to]>dist[node]+w[ed]) 113 { 114 dist[to]=dist[node]+w[ed]; 115 if(!vis[to]) 116 { 117 vis[to]=1; 118 que[tail++]=to; 119 } 120 } 121 if(fr[to]==a&&!vis[to]) 122 { 123 vis[to]=1; 124 que[tail++]=to; 125 } 126 } 127 } 128 printf("%0.1f\n",dist[des]); 129 } 130 return 0; 131 }
标签:ora 解析 小数 cstring sqrt can tail badge 保留
原文地址:https://www.cnblogs.com/smoncaff/p/9035827.html