VOJ 1006 - 晴天小猪历险记之HILL(经典DP)

parachutes 发表于 2007-10-28 19:09:05

在很久很久以前,有一个动物村庄,那里是猪的乐园(^_^),村民们勤劳、勇敢、善良、团结……
不过有一天,最小的小小猪生病了,而这种病是极其罕见的,因此大家都没有储存这种药物。所以晴天小猪自告奋勇,要去采取这种药草。于是,晴天小猪的传奇故事便由此展开……

这一天,他来到了一座深山的山脚下,因为只有这座深山中的一位隐者才知道这种药草的所在。但是上山的路错综复杂,由于小小猪的病情,晴天小猪想找一条需时最少的路到达山顶,但现在它一头雾水,所以向你求助。
山用一个三角形表示,从山顶依次向下有1段、2段、3段等山路,每一段用一个数字T(1<=T<=100)表示,代表晴天小猪在这一段山路上需要爬的时间,每一次它都可以朝左、右、左上、右上四个方向走(**注意**:在任意一层的第一段也可以走到本层的最后一段或上一层的最后一段)。
晴天小猪从山的左下角出发,目的地为山顶,即隐者的小屋。

输入格式 第一行有一个数n(2<=n<=1000),表示山的高度。
从第二行至第n+1行,第i+1行有i个数,每个数表示晴天小猪在这一段山路上需要爬的时间。

输出格式
一个数,即晴天小猪所需要的最短时间。

样例输入
5 1 2 3 4 5 6 10 1 7 8 1 1 4 5 6
样例输出
10

时间限制
各个测试点1s

注释
在山的两侧的走法略有特殊,请自己模拟一下,开始我自己都弄错了……

来源
Sunnypig

分析
本题是经典DP数字三角形的一个加强版。说是加强,是因为注释里的那句话。这题有两种做法,从上往下推和从下往上推,显然前者更简单一些。推状态转移方程的时候只需要想在某一点可以走到那一点。题目中说从一点可以向左上,右上,左,右走,这样方程就很显然了。 F[i, j] = MAX ( F[i, j], F[i, j-1]+A[i, j], F[i, j+1]+A[i, j], F[i-1, j-1]+A[i, j], F[i-1, j]+A[i, j]){2<=i<=n, 1<=j<=i}; 最后F[n, 1]就是答案了。

===================我是华丽的分割线======================
//ALGO:DP(O(N^2))
//PROG:VOJ1006
const
    maxn = 1001;
    maxm = 100000;
var
    n : longint;
    f : array [0..maxn, 0..maxn] of longint;
    a : array [0..maxn, 0..maxn] of longint;
procedure Init;
var
    i, j : longint;
begin
    readln(n);
    for i := 1 to n do begin
        for j := 1 to i do begin
            read(a[i, j]);
            f[i, j] := maxm;
        end;
        readln;
    end;
end;
procedure Dp;
var
    i, j : longint;
    flag : boolean;
begin
    f[1, 0] := a[1, 1];
    f[1, 1] := a[1, 1];
    f[1, 2] := a[1, 1];
    for i := 2 to n do begin
        repeat
            flag := true;
            f[i, 0] := f[i, i];
            f[i, i+1] := f[i, 1];
            for j := 1 to i do begin
                if (f[i, j] > f[i-1, j] + a[i, j]) then begin
                    f[i, j] := f[i-1, j] + a[i, j];
                    flag := false;
                end;
                if (f[i, j] > f[i, j+1] + a[i, j]) then begin
                    f[i, j] := f[i, j+1] + a[i, j];
                    flag := false;
                end;
                if (f[i, j] > f[i, j-1] + a[i, j]) then begin
                    f[i, j] := f[i, j-1] + a[i, j];
                    flag := false;
                end;
                if (f[i, j] > f[i-1, j-1] + a[i, j]) then begin
                    f[i, j] := f[i-1, j-1] + a[i, j];
                    flag := false;
                end;
            end;
            if flag then break; 
        until false;
    end;
    writeln(f[n, 1]);
end;
BEGIN
    Init;
    Dp;
END.

关键词(Tag): dp 动态规划 vijos


收藏: QQ书签 del.icio.us 订阅: Google 抓虾

最新评论

发表评论

* 昵称

已经注册过? 请登录

新用户请先注册 以便能显示头像及追踪评论回复

Email
网址
* 评论
表情
 
 

分类小组论坛
杂谈, 娱乐、八卦, 文学、艺术, 体育, 旅游、同城, 象牙塔, 情感, 时尚、生活, 星座, 科技

请注意遵守中华人民共和国法律法规, 如威胁到本站生存, 将依法向有关部门报告, 同时本站的相关记录可能成为对您不利的证据.

相关法律法规
全国人大常委会关于维护互联网安全的决定
中华人民共和国计算机信息系统安全保护条例
中华人民共和国计算机信息网络国际联网管理暂行规定
计算机信息网络国际联网安全保护管理办法
计算机信息系统国际联网保密管理规定