Codevs1041&&Vijos1119 car的旅行路線(最短路dijkstra)
Codevs1041&&Vijos1119 car的旅行路線(最短路)
題目描述
又到暑假了,住在城市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
數據範圍及提示 Data Size & Hint
如描述
解析:首先看見這道題就知道是最短路,這道題的重點是拆點和建邊,把圖建好了就相當於做出來了。這道題的建圖有點麻煩,主要是在直角坐標系裏的判斷,計算有點煩。
先輸入:
首先它是從A城市隨便哪個機場開始,所以對於開始城市,我們要特殊處理,把開始的城市的機場和這個城市其他的機場相連,每條邊賦值為0;然後就開始建其他邊,對於其他邊,直接跑for循環。
存儲用鏈表:
圖就建好了。就可以直接用spfa或dijkstra跑一下就行了,我用的是 pair優先隊列dijkstra算法。完整代碼在此
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cmath>
using namespace std;
typedef pair<double,int > pii;
priority_queue<pii,vector<pii>,greater<pii> >q;
struct node{
int v,next;
double c;
}e[2005*2];//鏈表存儲
int n,t,start,k,ende,head[405],vis[405];
double f[405];
struct kk{
int x[5],y[5],si;
}city[105];
void adda(int x,int y,double z)//鏈表存儲
{
e[k].v=y;
e[k].c=z;
e[k].next=head[x];
head[x]=k++;
}
double kao(int x,int y,int xi,int yi)
{
return sqrt((x-xi)*(x-xi)+(y-yi)*(y-yi));
}
void build()
{
for(int i=1;i<=n;i++)//從第一個城市跑
{
for(int j=1;j<=n;j++){//枚舉所有城市
if(i==start&&j==start){//對於開始城市特殊處理
adda(4*i-3,4*i-2,0);adda(4*i-3,4*i-1,0);adda(4*i-3,4*i,0);adda(4*i-2,4*i-1,0);adda(4*i-2,4*i,0);adda(4*i-1,4*i,0);
}
else{
for(int o=1;o<=4;o++)//枚舉每個飛機場
for(int h=1;h<=4;h++){
if(i==j&&o==h) continue;
if(i==j)//對於城市內部處理
adda((i-1)*4+o,(j-1)*4+h,kao(city[i].x[o],city[i].y[o],city[i].x[h],city[i].y[h])*city[i].si);
else //對於城市與城市的處理
adda((i-1)*4+o,(j-1)*4+h,kao(city[i].x[o],city[i].y[o],city[j].x[h],city[j].y[h])*t);
}
}
}
}
}
void dijkstra()
{
while(!q.empty())
{
int u=q.top().second;
q.pop();
if(vis[u]==1) continue;
vis[u]=1;
for(int i=head[u];i!=-1;i=e[i].next)
{
int vi=e[i].v;
if(f[vi]>f[u]+e[i].c)
{
f[vi]=f[u]+e[i].c;
q.push(make_pair(f[vi],vi));
}
}
}
}
int main()
{
memset(head,-1,sizeof(head));
for(int i=1;i<=405;i++)
f[i]=0x3f3f3f;
cin>>n>>t>>start>>ende;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d%d%d%d%d",&city[i].x[1],&city[i].y[1],&city[i].x[2],&city[i].y[2],&city[i].x[3],&city[i].y[3],&city[i].si);//輸入
int dis12=(city[i].x[1]-city[i].x[2])*(city[i].x[1]-city[i].x[2])+(city[i].y[1]-city[i].y[2])*(city[i].y[1]-city[i].y[2]);//1,2兩點距離的平方
int dis23=(city[i].x[2]-city[i].x[3])*(city[i].x[2]-city[i].x[3])+(city[i].y[2]-city[i].y[3])*(city[i].y[2]-city[i].y[3]);//2, 3兩點的平方
int dis13=(city[i].x[1]-city[i].x[3])*(city[i].x[1]-city[i].x[3])+(city[i].y[1]-city[i].y[3])*(city[i].y[1]-city[i].y[3]);//1,3 兩點的平方
//判斷直角求出第四個飛機場
if(dis12==dis23+dis13){
city[i].x[4]=city[i].x[1]-city[i].x[3]+city[i].x[2];
city[i].y[4]=city[i].y[1]-city[i].y[3]+city[i].y[2];
}
else if(dis13==dis12+dis23){
city[i].x[4]=city[i].x[1]-city[i].x[2]+city[i].x[3];
city[i].y[4]=city[i].y[1]-city[i].y[2]+city[i].y[3];
}
else {
city[i].x[4]=city[i].x[3]-city[i].x[1]+city[i].x[2];
city[i].y[4]=city[i].y[3]-city[i].y[1]+city[i].y[2];
}
}
build();
f[start]=0;
q.push(make_pair(f[start],start*4-3));
dijkstra();
double minn=0x3f3f3f;
for(int i=1;i<=4;i++)
if(minn>f[ende*4-4+i]) minn=f[ende*4-4+i];
printf("%.2f",minn);
return 0;
}
這道題解決了
Codevs1041&&Vijos1119 car的旅行路線(最短路dijkstra)