描述
又到暑假了,住在城市A的Car想和朋友一起去城市B旅遊。她知道每個城市都有四個飛機場,分別位於一個矩形的四個頂點上,同一個城市中兩個機場之間有一條筆直的高速鐵路,第I個城市中高速鐵路了的單位裡程價格為Ti,任意兩個不同城市的機場之間均有航線,所有航線單位裡程的價格均為t。
那麼Car應如何安排到城市B的路線才能儘可能的節省花費呢?她發現這並不是一個簡單的問題,於是她來向你請教。找出一條從城市A到B的旅遊路線,出發和到達城市中的機場可以任意選取,要求總的花費最少。
格式 輸入格式
第一行有四個正整數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個城市高速鐵路單位裡程的價格。 輸出格式
輸出最小費用(結果保留兩位小數) 範例 範例輸入
3 10 1 31 1 1 3 3 1 302 5 7 4 5 2 18 6 8 8 11 6 3
範例輸出
47.55
限制
每個測試點1s 來源
NOIP2001第四題
很明顯這是一個最短路的題目 最短路不是重點 重點是處理邊
因為邊太多了。。。而且還要自己找座標。。。
就當Dijk的模板題了
值得一提的是 同一城市的機場也可以走。。。怪不得不過範例。。。
#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<cmath>#include<iomanip>using namespace std;const int inf=999999999;struct self{ int i;double d; bool operator<(const self &a1) const { return a1.d==d?a1.i<i:a1.d<d; }};priority_queue<self>q;double d[511];struct side{int x,y;double w;}s[400021];int first[400021],nxt[400021];struct node{int x,y;}g[511];int w[511];int m,n,Start,End,Cost;int a,b,c;bool chuizhi(int a,int b,int c){ int ax=g[b].x-g[a].x,bx=g[c].x-g[a].x; int ay=g[b].y-g[a].y,by=g[c].y-g[a].y; if(ax*bx+ay*by==0)return true; return false;}void findforth(int i){ int pos=i*4; int a=pos-3,b=pos-2,c=pos-1; if(chuizhi(a,b,c)){g[pos].x=g[b].x-g[a].x+g[c].x;g[pos].y=g[b].y-g[a].y+g[c].y;} if(chuizhi(b,a,c)){g[pos].x=g[a].x-g[b].x+g[c].x;g[pos].y=g[a].y-g[b].y+g[c].y;} if(chuizhi(c,a,b)){g[pos].x=g[a].x-g[c].x+g[b].x;g[pos].y=g[a].y-g[c].y+g[b].y;}}void makeside(int x,int y,double w){ n++; s[n].x=x; s[n].y=y; s[n].w=w; nxt[n]=first[x]; first[x]=n;}double dis(int a,int b,int c){return sqrt((g[a].x-g[b].x)*(g[a].x-g[b].x)+(g[a].y-g[b].y)*(g[a].y-g[b].y))*c;}void dijk(){ int a,b; for(a=0;a<=m+4;a++)d[a]=inf; d[0]=0; q.push((self){0,0}); while(!q.empty()) { self u=q.top();q.pop(); if(u.d!=d[u.i])continue; for(int e=first[u.i];e!=-1;e=nxt[e]) if(d[s[e].y]>d[u.i]+s[e].w) { d[s[e].y]=d[u.i]+s[e].w; q.push((self){s[e].y,d[s[e].y]}); } }}int main(){ memset(first,-1,sizeof(first)); memset(nxt,-1,sizeof(nxt)); scanf("%d%d%d%d",&m,&Cost,&Start,&End); for(a=1;a<=m;a++) { for(b=a*4-3;b<=a*4-1;b++)scanf("%d%d",&g[b].x,&g[b].y); scanf("%d",&w[a]); findforth(a); for(b=a*4-3;b<=a*4;b++) for(c=a*4-3;c<=a*4;c++) if(b!=c)makeside(b,c,dis(b,c,w[a])); } m*=4; for(a=1;a<=m;a++) for(b=1;b<=m;b++) //if(abs(a-b)>=4) makeside(a,b,dis(a,b,Cost)); makeside(0,Start*4-3,0); makeside(0,Start*4-2,0); makeside(0,Start*4-1,0); makeside(0,Start*4,0); makeside(End*4-3,m+1,0); makeside(End*4-2,m+1,0); makeside(End*4-1,m+1,0); makeside(End*4,m+1,0); dijk(); cout<<fixed<<setprecision(2)<<d[m+1]<<'\n'; return 0;}