[DP][vijos1006]晴天小猪历险记之Hill

题目梗概

首先题目和数字三角形那道经典的DP题目描述一样,不过增加了两处不同:

1.同行之间可以相邻移动

2.位置(i,j)(i,j),它与(i-1,j-1)(i−1,j−1)以及(i-1,j)(i−1,j)相邻,特别的(i,1)(i,1)与(i-1,i-1)(i−1,i−1)相邻,且(i,i)(i,i)与(i-1,1)(i−1,1)相邻.

思考

首先第一点我们只要在数字三角形的基础上,加上每行的移动就可以了。

但是第二点就要注意了,这样的描述使DP变成了环形。

具体的解释看这位大佬(PowderHan大佬的想法)

f[i][j]表示第i行第j个点到目标终点(1,1)的最小时间
则转换为数字三角形问题,但是只是多了几种走法,不断更新最小值就好了
但是问题就来了,这样动态规划具有最优子结构吗?
注意这是个环形走法
答案是不成立于的,怎么说?
我们来看一下这样一个例子,假设某个数据的第某层的时间为
1,1,1,1,1,1
而从下往上推上来一开始的初值f[][]分别为
1,2,4,3,9,10
那么我们先进行第一次同行内从左往右的更新的递推(可以看代码内的推法)
则有更新为
1,2,3,3,4,5
再从右往左更新推一遍
1,2,3,3,4,2(左端的1可以走到右端来更新了右端的时间)
那么这样就完了吗?不,我们可以发现我们可以用新更新的2去更新推出更优的解
则应该为
1,2,3,3,3,2
所以从这个样例中我们可以看出一次两边推根本的不出最优解
为什么呢?
我们看某次往一边推,由于是环形,所以可能从右向左推,用第一个更新了最右端的那个点
但是最右端的那个点在更新之前已经推完了右边数的第二个点
就是新更新的这个右端点并没有用来当作"下家"来更新别的点使别的点更优
同理从左往右也是一样
那么怎么办呢?
我们可以推两遍,这样假如更新了某个端点的值,在下一次递推时一定能用来作为"下家"尝试再更新别的点
那么这样问题就解决了
我们总结一下做法
首先每个点的初值为从下一层走到这一层的两个更优解
然后我们在同层迭代递推,左推一遍右推一遍,然后再重复推一遍

问题就解决了,so easy.

代码实现:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

const int maxn=1005;
int a[maxn][maxn];
int f[maxn][maxn];
int n;

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=i;j++)
        cin>>a[i][j];
    f[1][1]=a[1][1];//终点处就直接是该点时间
    for(int i=2;i<=n;i++)//一层一层往上推
    {
        for(int j=2;j<i;j++)//先求出从上一层推出来的最小值
            f[i][j]=min(f[i-1][j],f[i-1][j-1])+a[i][j];
        f[i][1]=min(f[i-1][1],f[i-1][i-1])+a[i][1];//特殊边界点处理
        f[i][i]=min(f[i-1][i-1],f[i-1][1])+a[i][i];//特殊边界点处理
        //同一层更新最优解
        for(int k=i-1;k>0;k--)//从右往左推 从右往左走的情况更新
            f[i][k]=min(f[i][k],f[i][k+1]+a[i][k]);
        f[i][i]=min(f[i][i],f[i][1]+a[i][i]);

        for(int l=2;l<=i;l++)//从左往右推 从左往右走的情况更新
            f[i][l]=min(f[i][l],f[i][l-1]+a[i][l]);
            f[i][1]=min(f[i][1],f[i][i]+a[i][1]);

        for(int k=i-1;k>0;k--)//再推一遍从右往左推 从右往左走的情况更新
            f[i][k]=min(f[i][k],f[i][k+1]+a[i][k]);
            f[i][i]=min(f[i][i],f[i][1]+a[i][i]);

        for(int l=2;l<=i;l++)//再推一遍从左往右推 从左往右走的情况更新
            f[i][l]=min(f[i][l],f[i][l-1]+a[i][l]);
                f[i][1]=min(f[i][1],f[i][i]+a[i][1]);
    }
    cout<<f[n][1]<<endl;
}
时间: 2025-01-03 12:30:06

[DP][vijos1006]晴天小猪历险记之Hill的相关文章

回档|晴天小猪历险记之hill

背景 Background 在很久很久以前,有一个动物村庄,那里是猪的乐园(^_^),村民们勤劳.勇敢.善良.团结…… 不过有一天,最小的小小猪生病了,而这种病是极其罕见的,因此大家都没有储存这种药物.所以晴天小猪自告奋勇,要去采取这种药草.于是,晴天小猪的传奇故事便由此展开…… 描述 Description 这一天,他来到了一座深山的山脚下,因为只有这座深山中的一位隐者才知道这种药草的所在.但是上山的路错综复杂,由于小小猪的病情,晴天小猪想找一条需时最少的路到达山顶,但现在它一头雾水,所以向你

vijosP1006 晴天小猪历险记之Hill

链接:https://vijos.org/p/1006 [思路] 图上DP. 这个题的递推顺序是关键.先从上一行得到最小值,然后从本行比较最小值,注意本行.本行与上一行之间的第一段与最后一段是相通的. [代码] 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 5 using namespace std

VIjos 晴天小猪历险记之Number (搜索+链表hash)

背景 话说上一回,晴天小猪不畏千难万险.千辛万苦.千磨万难……终于爬上了那座深山,来到了那位隐者的小屋中,但它不知道,有一个问题正等待着它……晴天小猪一推开门,就发现那里……空无一人?但在屋中央有一个石桌,上面有一些字(强吧),最大的几个:如要见我,先过了这道关再说!晴天小猪定睛一看,终于发现桌上密密麻麻布满了字,费了九天二猪之力,终于将题目看完,大意是:为了维护世界的和平……我们需要让九位勇士组成一个3*3的阵型去屠龙,但是这个阵型的要求很奇特,要九个人按照强弱依次编号1~9,且阵型中每行.每

数字三角形合集

简单介绍 数字三角形这东西,出现了有一定的年头了.于是,出现了一些变种-- 眼下已知的题目 Codevs1220 数字三角形 这题是原版IOI1994啊-- f[i][j]=a[i][j]+max(f[i-1][j],f[i-1][j-1]). Codevs2193 数字三角形ww 和 Codevs2198 数字三角形www 改了.必须得经过一个点.而且2198是2193的数据规模上的加强版. 然而这并没有什么L用,仅仅需让必须经过的点的权值加上一个特别大的值,最后的结果再减去这个值即可了. 实

[SinGuLaRiTy] 动态规划题目复习

[SinGuLaRiTy-1026] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. [UVA 1025] A Spy in the Metro 题目描述 特工玛利亚被送到S市执行一个特别危险的任务.她需要利用地铁完成他的任务,S市的地铁只有一条线路运行,所以并不复杂. 玛利亚有一个任务,现在的时间为0,她要从第一个站出发,并在最后一站的间谍碰头.玛利亚知道有一个强大的组织正在追踪她,她知道如果一直呆在一个车站,她会有很大的被抓的风险,躲

codeforces Hill Number 数位dp

http://www.codeforces.com/gym/100827/attachments Hill Number Time Limits:  5000 MS   Memory Limits:  200000 KB 64-bit interger IO format:  %lld   Java class name:  Main Description A Hill Number is a number whose digits possibly rise and then possibl

(中等) CF 311B Cats Transport,斜率优化DP。

Zxr960115 is owner of a large farm. He feeds m cute cats and employs p feeders. There's a straight road across the farm and n hills along the road, numbered from 1 to n from left to right. The distance between hill i and (i - 1) is di meters. The fee

3890: [Usaco2015 Jan]Meeting Time( dp )

简单的拓扑图dp.. A(i, j), B(i, j) 表示从点 i 长度为 j 的两种路径是否存在. 用bitset就行了 时间复杂度O(m) ---------------------------------------------------------------- #include<bits/stdc++.h> #define clr(x, c) memset(x, c, sizeof(x)) #define rep(i, n) for(int i = 0; i < n; ++

Problem D. What a Beautiful Lake dp

Problem D. What a Beautiful Lake Description Weiming Lake, also named "Un-named Lake", is the most famous scenic spot in Peking University. It is located in the north of the campus and is surrounded by walking paths, small gardens, and old red b