博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

汤姆斯的天堂梦(par)

Posted on 2010-10-11 21:15  深处的心扉  阅读(325)  评论(0)    收藏  举报

【问题描述】

汤姆斯生活在一个等级为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原创,转载请注明出处)