1. 程式人生 > >P1744 采購特價商品

P1744 采購特價商品

概覽 運算 double類型 利用 正是 角度 公式 http printf

原題鏈接 https://www.luogu.org/problemnew/show/P1744

一道最短路的模板題.....很簡單吧

求最短路的方法有很多,但是對於剛學完Floyd的我,只會用這個.......雖然有點慢,但是也能AC

Floyd算法

1.定義概覽

Floyd-Warshall算法(Floyd-Warshall algorithm)是解決任意兩點間的最短路徑的一種算法,可以正確處理有向圖或負權的最短路徑問題,同時也被用於計算有向圖的傳遞閉包。Floyd-Warshall算法的時間復雜度為O(N3),空間復雜度為O(N2)。

2.算法描述

算法思想原理:

Floyd算法是一個經典的動態規劃算法。用通俗的語言來描述的話,首先我們的目標是尋找從點i到點j的最短路徑。從動態規劃的角度看問題,我們需要為這個目標重新做一個詮釋(這個詮釋正是動態規劃最富創造力的精華所在)

從任意節點i到任意節點j的最短路徑不外乎2種可能,1是直接從i到j,2是從i經過若幹個節點k到j。所以,我們假設Dis(i,j)為節點u到節點v的最短路徑的距離,對於每一個節點k,我們檢查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,證明從i到k再到j的路徑比i直接到j的路徑短,我們便設置Dis(i,j) = Dis(i,k) + Dis(k,j),這樣一來,當我們遍歷完所有節點k,Dis(i,j)中記錄的便是i到j的最短路徑的距離。

我們可以開一個n*n的鄰接矩陣,記錄聯通情況:f[i][j]如果為1,則說明i到j聯通;如果為∞,則說明不連通(之所以用∞的原因是比較的時候無窮大一定比任何除無窮大以外的數的和都大,這樣就不會把∞算進去),然後可以進一步將f[i][j]=1的地方利用兩點間距離公式將1換成具體的距離

代碼如下:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n,m,x,y,a[101][2],aa,bb;         //a數組存放坐標 
double b[101][101];                  //b數組存放最短路,註意double類型 
int main()
{
    cin>>n;                          //n個點 
    for
(int i=1;i<=n;i++) cin>>a[i][0]>>a[i][1]; //橫縱坐標 cin>>m; //m處聯通 memset(b,0x7f,sizeof(b)); //先將全部的元素賦為無窮大 for(int i=1;i<=m;i++) { cin>>x>>y; //點x與點y是聯通的 b[x][y]=b[y][x]=sqrt(pow((double)(a[x][0]-a[y][0]),2)+pow((double)(a[x][1]-a[y][1]),2)); //利用鄰接矩陣的對稱性減少一半運算,兩點間距離公式算距離,註意改成double類型 } for(int k=1;k<=n;k++) //Floyd算法,O(n^3)復雜度 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j&&i!=k&&j!=k&&((b[i][k]+b[k][j])<b[i][j])) b[i][j]=b[i][k]+b[k][j]; //如果第i點和第j點間有個間接點k使得第i個點到第k個點的距離+k個點到第j個點的距離<小於第i個點到第j個點的直接距離,則將最短距離更新 cin>>aa>>bb; //題目要求的第aa個點到第bb個點的矩陣 printf("%.2lf",b[aa][bb]); //直接輸出 return 0; }

完結撒花qaq~

P1744 采購特價商品