【NOIP2018普及級別】危險係數
阿新 • • 發佈:2019-01-09
時間限制: 1000 ms 空間限制: 131072 KB
題目描述
FJ在一條船上,海上有N(1<=N<=100)島,編號為1..N,現在他的任務是按照一個給定訪問次序A_1,A_2,….A_M去探索這M(2<=M<=10,000)個島嶼,已經知道任意兩個島嶼之間的危險係數,讓你找出一個探索序列,只需滿足你的探索序列包含給定的A_1..A_M這個序列就可以(不一定要連續),使得總的危險係數最小。
輸入
第1行: 兩個數, N 和 M
第 2..M+1行: 第i+1行表示給定的序列中第i個島嶼A_i
第M+2..N+M+1行:每行N個整數,表示島嶼之間的危險係數,對角線上一定是0。
輸出
輸出滿足要求的最小危險係數
樣例輸入
3 4
1
2
1
3
0 5 1
5 0 2
1 2 0
樣例輸出
7
資料範圍限制
提示
【樣例說明】
輸出解釋:我們可以按照1,3,2,3,1,3的順序去探索,滿足了規定了序列是該序列的字序列,危險係數為(1,3)+(3,2)+(2,3)+(3,1)+(1,3)=7。
思路:要使危險係數最小,就要求出多源最短路徑,並且要包含給出的指定路徑,這裡要用到Floyd演算法來做
過程:1.path儲存指定的路徑,mindanger存每條邊的危險係數(邊權)
2.Floyd求最小生成樹,沿指定路徑走,若某條彎路的危險係數比走一條路還要小,就將小值ik+kj賦予ij
3.path,path+1也就是每一條邊,此時mindanger中儲存的邊權都是最小的
程式碼:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<vector> #include<stack> #include<queue> #define MAXA 10001 #define INF 0x3f using namespace std; int n,m,path[MAXA],mindanger[MAXA][MAXA]; int main() { scanf("%d %d",&n,&m); for(int i=1;i<=m;i++) scanf("%d",&path[i]); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { scanf("%d",&mindanger[i][j]); } for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) if(i!=k) for(int j=1;j<=n;j++) if(i!=j && j!=k) if(mindanger[i][k] + mindanger[k][j] < mindanger[i][j]) mindanger[i][j] = mindanger[i][k] + mindanger[k][j]; long long dist = 0; for(int i=1;i<m;i++) dist += mindanger[path[i]][path[i+1]]; printf("%d",dist); }