危险系数

来源:互联网 发布:美国金融研究生 知乎 编辑:程序博客网 时间:2024/04/30 05:47

前言
“师太,你等着,老衲去让佛祖赐婚!”欢迎来到嘟嘟课堂。今天,嘟嘟老师讲一道图论题——危险系数。
题目描述
FJ在一条船上,海上有N(1<=N<=100)岛,编号为1..N,现在他的任务是按照一个给定访问次序A1,A2,….AM去探索这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。
思路
本题可能大家一开始没读懂,嘟嘟老师也是这样,给大家解释一下:你要按照1-2-1-3的路线去旅行,但是从第一个岛到第二个岛路程为5,比较远,还不如先从一个岛到第三个岛,再从第三个岛到第二个岛,只需要3的路程。
本题可以中转,或许1-2的路程还木有1-3-4-5-6-7-8-9-2的短。所以,这题我们可以用图论中的floyd(弗洛伊德)算法。有些童鞋可能会用SPFA(斯帕法)做本题,也是可以的,但是嘟嘟老师推荐用弗洛伊德,比较简单。
如果没学过弗洛伊德的,可以到网上去查一查。弗洛伊德算法就是专门处理这种中转的问题的(不管你会中转几次)
以下给出弗洛伊德代码:

for k:=1 to n do        begin                for i:=1 to n do                begin                        for j:=1 to n do                                if (b[i,j]>b[i,k]+b[k,j]) then b[i,j]:=b[i,k]+b[k,j];                end;        end;        for i:=1 to m-1 do                inc(ans,b[a[i],a[i+1]]);

(其中A【i】表示旅行必须经过的第i个岛屿,B【i,j】表示第i个岛屿到第j个岛屿的最短距离。)
代码

ar        a:array[1..10000] of longint;        b:array[1..100,1..100] of longint;        i,j,k,n,m,ans:longint;begin        readln(n,m);        for i:=1 to m do                readln(a[i]);        for i:=1 to n do                for j:=1 to n do                        read(b[i,j]);        for k:=1 to n do        begin                for i:=1 to n do                begin                        for j:=1 to n do                                if (b[i,j]>b[i,k]+b[k,j]) then b[i,j]:=b[i,k]+b[k,j];                end;        end;        for i:=1 to m-1 do                inc(ans,b[a[i],a[i+1]]);        writeln(ans);end.
原创粉丝点击