[NOIP提高組2001]Car的旅行路線
阿新 • • 發佈:2019-02-04
http://caioj.cn/problem.php?id=1507
問題描述:
又到暑假了,住在城市A的Car想和朋友一起去城市B旅遊。她知道每個城市都有四個飛機場,分別位於一個矩形的四個頂點上,同一個城市中兩個機場之間有一條筆直的高速鐵路,第I個城市中高速鐵路了的單位里程價格為Ti,任意兩個不同城市的機場之間均有航線,所有航線單位里程的價格均為t。
那麼Car應如何安排到城市B的路線才能儘可能的節省花費呢?她發現這並不是一個簡單的問題,於是她來向你請教。找出一條從城市A到B的旅遊路線,出發和到達城市中的機場可以任意選取,要求總的花費最少
輸入:
第一行為一個正整數n(0≤n≤10),表示有n組測試資料。
第二行有四個正整數S,T,A,B。其中S表示城市的個數,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個城市高速鐵路單位里程的價格。
輸出:
輸出最小費用(結果保留兩位小數)
題解:
首先,輸入只有三個點,所以我們要求第四個點,這裡我們可以用迭代法不停迴圈,直到x1->x2,x2->x3這兩條直線垂直。那麼第四個點的座標就是x1-x2+x3這裡畫個圖就知道了。
然後直接建邊,跑最短路,由於資料範圍不大直接floyd就好了。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define inf 10000000
#define get(x) (x-1)*4+1
using namespace std;
int n;
int s,st,ed,ap;
double T;
struct node{
double x[4],y[4];
}sa[105];//第i個城市機場的x,y
double f[4050][4050];//從第i個機場到第j個機場的最短距離
void getfour(int x)//求第四個點
{
double tx[4],ty[4];
memcpy(tx,sa[x].x,sizeof(tx));
memcpy(ty,sa[x].y,sizeof(ty));
while((tx[0]-tx[1])*(tx[2]-tx[1])+(ty[0]-ty[1])*(ty[2]-ty[1]))//畫個圖就知道了,這樣可以判斷直線是否垂直
{
int tt=tx[0];tx[0]=tx[1];tx[1]=tx[2];tx[2]=tt;
tt=ty[0];ty[0]=ty[1];ty[1]=ty[2 ];ty[2]=tt;
}
sa[x].x[3]=tx[0]-tx[1]+tx[2];
sa[x].y[3]=ty[0]-ty[1]+ty[2];
}
double dis(int x1,int y1,int x2,int y2)
{
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int main()
{
scanf("%d",&n);
while(n--)
{
scanf("%d%lf%d%d",&s,&T,&st,&ed);
if(st==ed) {printf("0.00\n");continue;}
ap=s*4;
for(int i=1;i<=ap;i++)
for(int j=1;j<=ap;j++)
{
f[i][j]=inf;
}
for(int i=1;i<=s;i++)
{
for(int j=0;j<3;j++)
scanf("%lf%lf",&sa[i].x[j],&sa[i].y[j]);
getfour(i);//得到第四個點
//求同一城市,機場間的距離
double yu;
scanf("%lf",&yu);
for(int u=0;u<4;u++)
{
for(int v=0;v<4;v++)
{
if(u==v) continue;
f[get(i)+u][get(i)+v]=dis(sa[i].x[u],sa[i].y[u],sa[i].x[v],sa[i].y[v])*yu;
}
}
}
//求不同城市的機場間的距離
for(int i=1;i<=s;i++)
{
for(int j=1;j<=s;j++)
{
if(i==j) continue;
for(int u=0;u<4;u++)
{
for(int v=0;v<4;v++)
{
f[get(i)+u][get(j)+v]=dis(sa[i].x[u],sa[i].y[u],sa[j].x[v],sa[j].y[v])*T;
//
}
}
}
}
//floyd求最短路
for(int k=1;k<=ap;k++)
for(int i=1;i<=ap;i++)
for(int j=1;j<=ap;j++)
{
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
//
}
double ans=inf;
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
{
ans=min(ans,f[get(st)+i][get(ed)+j]);
//printf("%.2lf\n",f[get(st)+i][get(ed)+j]);
}
printf("%.2lf\n",ans);
}
}