【问题描述】
汤姆斯生活在一个等级为0的星球上。那里的环境极其恶劣,每天12小时的工作和成堆的垃圾让人忍无可忍。他向往着等级为N的星球上天堂般的生活。
有一些航班将人丛低等级的星球送上高一级的星球,有时需要向驾驶员支付一定金额的费用,有时却又可以得到一定的金钱。
汤姆斯预先知道了从0等级星球去N等级星球所有的航线和需要支付(或者可以得到)的金钱,他想寻找一条价格最低(甚至获得金钱最多)的航线。
【输入】
第一行一个正整数N(N≤100),接下来的数据可分为N个段落
每段的第一行一个整数Ki(Ki≤100),表示等级为i的星球有Ki个。
接下来的Ki中第Tij行依次表示与等级为i,编号为j的星球相连的等级为i-1的星球的编号和此航线需要的费用(正数表示支出,负数表示受益,费用的绝对值不超过1000)。每行以0结束,每行的航线数≤100。
【输出】
输出所需(或所得)费用。整数表示支出,负数表示收益。
【输入样例】
3
2
115 0
1 50
3
1 -5 210 0
1 30
2 400
2
1 1 2 5 3 -5 0
2 -193 -20 0
【输出样例】
-1
【数据范围】
对于100%的数据N≤100 Ki≤100。
【样例解释】
如右图

题目分析:
从题目上看,乍一看有点像图论问题,可是仔细分析一下原来是动态规划
仔细分析题目,不难得到动态转移方程
f[i,j]=min(f[i-1,k]+dist[i-1,k][i,j])
其中dist[i-1,k][i,j]表示第i-1级的k号星球与第i级的j号星球的距离
这样开的数组为四维,有些勉强,仔细考虑一下可以压缩到三维:
f[i,j]=min(f[i-1,k]+dist[k][i,j])
因为只是第i-1级与i级所以前一维可以不要
不罗嗦了,贴代码
1 program par;
2 var dist:array[0..100,0..100,0..100]of integer;//前一级别与当前级别的i号星球的费用
3 f:array[0..100,0..100]of longint; //记录状态
4 a:array[0..100]of integer; //记录当前级别的星球个数
5 n,i,min:longint;
6 procedure init;
7 var i,j,m,x,k,s,t:integer;
8 begin
9 readln(n);
10 k:=0;
11 for i:=1 to n do
12 begin
13 readln(m);
14 for j:=1 to m do
15 begin
16 read(x);
17 t:=x;
18 inc(a[i]);
19 dist[x][i,j]:=10000; //初始最大
20 while x<>0 do //从所有的数据中找到最小的
21 begin
22 read(s);
23 t:=x;
24 if s<dist[x][i,j] then dist[x][i,j]:=s; //更新
25 read(x);
26 if (t<>x)and(dist[x][i,j]=0) then
27 dist[x][i,j]:=10000; //初始最大
28 end;
29 end;
30 end;
31 end;
32
33 procedure main;
34 var i,j,k:longint;
35 begin
36 for i:=1 to n do
37 for j:=1 to a[i] do
38 f[i,j]:=10000; //初始化
39 f[0,0]:=0;
40 a[0]:=0;
41 for i:=1 to a[1] do
42 begin
43 f[1,i]:=dist[1][1,i];
44 end;
45 for i:=1 to n do
46 for j:=1 to a[i] do
47 for k:=1 to a[i-1] do
48 if ((f[i,j]>f[i-1,k]+dist[k][i,j])and(dist[k][i,j]<>0)) then
49 f[i,j]:=f[i-1,k]+dist[k][i,j]; //动态转移方程
50 end;
51 begin
52 init;
53 main;
54 min:=10000;
55 for i:=1 to a[n] do
56 if min>f[n,i] then
57 min:=f[n,i];
58 writeln(min);//输出最小值
59 end.
(-----------------------------------------------------------------由JackerJay原创,转载请注明出处)
浙公网安备 33010602011771号