1. 程式人生 > >Codevs1041&&Vijos1119 car的旅行路線(最短路dijkstra)

Codevs1041&&Vijos1119 car的旅行路線(最短路dijkstra)

greate rip image nod car 處理 安排 eat gre

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)