1. 程式人生 > >演算法訓練 Car的旅行路線 藍橋杯

演算法訓練 Car的旅行路線 藍橋杯

描述

又到暑假了,住在城市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個城市高速鐵路單位里程的價格。

輸出格式

輸出最小費用(結果保留兩位小數)

樣例1

樣例輸入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

樣例輸出1

47.55

限制

每個測試點1s

最短路徑問題之兩點最短路徑

Floryd—Warshall演算法

要理解這個演算法先要了解Floyd演算法

Floyd演算法的核心是dp[k][i][j],意思是從i到j,中間使用前k個節點或是不用節點,得到的最短邊權和。

遞推式dp[k][i][j]=min(dp[k-1][i][j],dp[k-1][i][k]+dp[k-1][k][j])

整個過程就是在維護n個表,每個表記錄使用前k個節點得到的最優值。

通常可以在任何圖使用,包括有向圖,負權圖。

F-W演算法簡化了演算法,使用一張表完成n張表的任務,每次更新都要使用前面那個表k行k列的資料,而更新對k行k列資料不產生影響,所以這種簡化可行。

這道題還有其他特性,在程式碼裡註釋了。

時間複雜度O(n^3),空間複雜度O(n^2)

#include <cstring>
#include <cstdio>
#include<cmath>
#include <queue>
#include<algorithm>
using namespace std;
#define min(a,b) ((a<b)?(a):(b))
#define swap(a,b) temp=a;a=b;b=temp
const float INF=99999.9999;
void deter(float x1,float y1,float x2,float y2,float x3,float y3,float *x,float *y){
    float temp;
    if((x1-x2)*(x3-x2)+(y1-y2)*(y3-y2)==0){//判斷哪個點是直角點
        swap(x1,x2);swap(y1,y2);
    }
    else if((x1-x3)*(x2-x3)+(y1-y3)*(y2-y3)==0){
        swap(x1,x3);swap(y1,y3);
    }
    *x=x2+x3-x1;
    *y=y2+y3-y1;
    }
struct city{
float x[4];
float y[4];
float T;
city(float x1,float y1,float x2,float y2,float x3,float y3,float t){
x[0]=x1;x[1]=x2;x[2]=x3;
y[0]=y1;y[1]=y2;y[2]=y3;
deter(x1,y1,x2,y2,x3,y3,&x[3],&y[3]);
T=t;
}
}*c[1010];
float dp[410][410];
float dist(float x1,float y1,float x2,float y2){
return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
}
void init(int s,float t){
  int i,j;
  for(i=0;i<4*s;i++){//建立下標與點構建關係:i/4==城市編號,i%4==點在城市內的編號
    for(j=0;j<4*s;j++){
        if(i/4==j/4){
            dp[i][j]=dist(c[i/4]->x[i%4],c[i/4]->y[i%4],c[j/4]->x[j%4],c[j/4]->y[j%4])*c[i/4]->T;
        }
        else{
            dp[i][j]=dist(c[i/4]->x[i%4],c[i/4]->y[i%4],c[j/4]->x[j%4],c[j/4]->y[j%4])*t;
        }
    }
  }
}
void FW(int s){
for(int k=0;k<4*s;k++){
    for(int i=0;i<4*s;i++){
        for(int j=0;j<4*s;j++){
                dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
        }
    }
}
}
int main(){
int A,B;
int s;
float t,co;
float x1,x2,x3,y1,y2,y3;
    memset(dp,0,sizeof(dp));
    scanf("%d%f%d%d",&s,&t,&A,&B);
    for(int i=0;i<s;i++){
        scanf("%f%f%f%f%f%f%f",&x1,&y1,&x2,&y2,&x3,&y3,&co);//注意使用float,用double的話,1儲存為-0,00
        c[i]=new city(x1,y1,x2,y2,x3,y3,co);
    }
    init(s,t);
    FW(s);
    float q=INF;
    for(int i=4*A-4;i<4*A;i++)//A,B是城市編號,不是點在表格裡的編號
        for(int j=4*B-4;j<4*B;j++)
        q=min(q,dp[i][j]);
    printf("%.1f",q);
    for(int i=0;i<s;i++){
        delete c[i];
}
return 0;}





相關推薦

演算法訓練 Car旅行路線 藍橋

描述 又到暑假了,住在城市A的Car想和朋友一起去城市B旅遊。她知道每個城市都有四個飛機場,分別位於一個矩形的四個頂點上,同一個城市中兩個機場之間有一條筆直的高速鐵路,第I個城市中高速鐵路了的單位里程價格為Ti,任意兩個不同城市的機場之間均有航線,所有航線單位里程的價格

演算法訓練 比較字串 (藍橋C++)

先上程式碼吧! #include<iostream> #include<algorithm> #include<string> #include<cstring> #include<queue>

演算法訓練 方格取數 藍橋

問題描述   設有N*N的方格圖(N<=10),我們將其中的某些方格中填入正整數,而其他的方格中則放入數字0。   某人從圖的左上角的A 點(1,1)出發,可以向下行走,也可以向右走,直到到達右下角的B點(N,N)。在走過的路上,他可以取走方格中的數(取走後的方格中將

演算法訓練 K好數 藍橋

對於30%的資料,KL <= 106; 對於50%的資料,K <= 16, L <= 10; 對於100%的資料,1 <= K,L <= 100。 本身想用搜索,然後資料太大了,看了提示,要用動態規劃。 也不能算典型的動態規劃,因為不存在最優子結構,只是用了重複利用

藍橋 演算法訓練 字母圖形

問題描述 利用字母可以組成一些美麗的圖形,下面給出了一個例子: ABCDEFG BABCDEF CBABCDE DCBABCD EDCBABC 這是一個5行7列的圖形,請找出這個圖形的規律,並輸出一個n行m列的圖形。 輸入格式 輸入一行

藍橋 演算法訓練 區間k大數查詢

明明是一個水題卻wrong answer了很多遍。。 還是因為對最基礎的氣泡排序概念不清。蠢死算了。 這下終於搞清楚了。 問題描述 給定一個序列,每次詢問序列中第l個數到第r個數中第K大的數是哪個。 輸入格式 第一行包含一個數

藍橋 ALGO-47 演算法訓練 蜜蜂飛舞

問題描述“兩隻小蜜蜂呀,飛在花叢中呀……” 話說這天天上飛舞著兩隻蜜蜂,它們在跳一種奇怪的舞蹈。用一個空間直角座標系來描述這個世界,那麼這兩隻蜜蜂初始座標分別為(x1,y1,z1),(x2,y2,z2)  。在接下來它們將進行n次飛行,第i次飛行兩隻蜜蜂分別按照各自的速度向量飛行ti個單位時間。

藍橋-演算法訓練 未名湖邊的煩惱 (遞迴)

 演算法訓練 未名湖邊的煩惱   時間限制:1.0s   記憶體限制:256.0MB      問題描述   每年冬天,北大

[藍橋][演算法訓練VIP]猴子分蘋果

題目描述 秋天到了,n只猴子採摘了一大堆蘋果放到山洞裡,約定第二天平分。這些猴子很崇拜猴王孫悟空,所以都想給他留一些蘋果。第一隻猴子悄悄來到山洞,把蘋果平均分成n份,把剩下的m個蘋果吃了,然後藏起來一份,最後把剩下的蘋果重新合在一起。這些猴子依次悄悄來到山洞,都做同樣的操作,恰好每次

藍橋演算法訓練 最大最小公倍數

時間限制:1.0s   記憶體限制:256.0MB 問題描述 已知一個正整數N,問從1~N-1中任選出三個數,他們的最小公倍數最大可以為多少。 輸入格式 輸入一個正整數N。 輸出格式 輸出一個整數,表示你找到的最小公倍數。 樣例輸入 9 樣例輸出

藍橋 演算法訓練 ALGO-81 動態陣列使用

演算法訓練 動態陣列使用 時間限制:1.0s 記憶體限制:512.0MB 從鍵盤讀入n個整數,使用動態陣列儲存所讀入的整數,並計算它們的和與平均值分別輸出。要求儘可能使用函式實現程式程式碼。平均值為小數的只保留其整數部分。 樣例輸入: 5 3 4 0 0 2 樣例輸出: 9 1 樣例

藍橋 演算法訓練 ALGO-122 未名湖邊的煩惱 遞迴 遞推

演算法訓練 未名湖邊的煩惱 時間限制:1.0s 記憶體限制:256.0MB 問題描述   每年冬天,北大未名湖上都是滑冰的好地方。北大體育組準備了許多冰鞋,可是人太多了,每天下午收工後,常常一雙冰鞋都不剩。   每天早上,租鞋視窗都會排起長龍,假設有還鞋的m個,有需要租鞋的n個。現在

藍橋 演算法訓練 ALGO-116 最大的算式 動態規劃 資源分配型別(最大乘積)

演算法訓練 最大的算式 時間限制:1.0s 記憶體限制:256.0MB 問題描述   題目很簡單,給出N個數字,不改變它們的相對位置,在中間加入K個乘號和N-K-1個加號,(括號隨便加)使最終結果儘量大。因為乘號和加號一共就是N-1個了,所以恰好每兩個相鄰數字之間都有一個符號。例如:

藍橋 演算法訓練 ALGO-101 圖形顯示 迴圈語句

演算法訓練 圖形顯示 時間限制:1.0s 記憶體限制:512.0MB 問題描述   編寫一個程式,首先輸入一個整數,例如5,然後在螢幕上顯示如下的圖形(5表示行數):   * * * * *   * * * *   * * *   * *   * 分析:第一行輸出n個星號,

藍橋 演算法訓練 ALGO-97 排序 迴圈語句

演算法訓練 排序 時間限制:1.0s 記憶體限制:512.0MB 問題描述   編寫一個程式,輸入3個整數,然後程式將對這三個整數按照從大到小進行排列。   輸入格式:輸入只有一行,即三個整數,中間用空格隔開。   輸出格式:輸出只有一行,即排序後的結果。   輸入輸出樣例 樣例輸入

藍橋 演算法訓練 ALGO-95 2的次冪表示

演算法訓練 2的次冪表示 時間限制:1.0s 記憶體限制:512.0MB 問題描述   任何一個正整數都可以用2進製表示,例如:137的2進製表示為10001001。   將這種2進製表示寫成2的次冪的和的形式,令次冪高的排在前面,可得到如下表達式:137=27+23+2^0   現

藍橋 演算法訓練 ALGO-92 字首表示式 字元操作 數學知識

演算法訓練 字首表示式 時間限制:1.0s 記憶體限制:512.0MB 提交此題 問題描述   編寫一個程式,以字串方式輸入一個字首表示式,然後計算它的值。輸入格式為:“運算子 物件1 物件2”,其中,運算子為“+”(加法)、“-”(減法)、“*”(乘法)或“/”(除法),運算物件為

藍橋 演算法訓練 ALGO-91 Anagrams問題 陣列運算 字元操作

演算法訓練 Anagrams問題 時間限制:1.0s 記憶體限制:512.0MB 提交此題 問題描述   Anagrams指的是具有如下特性的兩個單詞:在這兩個單詞當中,每一個英文字母(不區分大小寫)所出現的次數都是相同的。例如,“Unclear”和“Nuclear”、“Rimon”

藍橋 演算法訓練 ALGO-90 出現次數最多的整數 陣列運算

演算法訓練 出現次數最多的整數 時間限制:1.0s 記憶體限制:512.0MB   問題描述   編寫一個程式,讀入一組整數,這組整數是按照從小到大的順序排列的,它們的個數N也是由使用者輸入的,最多不會超過20。然後程式將對這個陣列進行統計,把出現次數最多的那個陣列元素值打印出來。