cqyz oj | 【训练题】HB办证 P1419 | DP动态规划

Description

HB要办个签证,办证处是一座 M 层的大楼,每层楼都有 N 个办公室,编号为1..N,每个办公室有一个签证员,签证需要让第 M 层的某个签证员盖章才有效。每个签证员都要满足下面三个条件之一才会给HB盖章:

  1. 这个签证员在1楼。
  2. HB的签证已经给这个签证员的正楼下(房间号相同)的签证员盖过章了。
  3. HB的签证已经给这个签证员的相邻房间(房间号相差1,楼层相同)的签证员盖过章了。

每个签证员盖章都要收取一定费用,这个费用不超过1000000000。找出费用最小的盖章路线,使签证生效。

Input

第1行两个整数 M 和 N 。  接下来M行每行 N 个整数,第i行第j个数表示第i层的第j个签证员收取的费用。

Output

  输出最小的费用。

Sample Input 1

3 4
10 10 1 10
2 2 2 10
1 10 10 10

Sample Output 1

8

Hint

1<=M<=100,1<=N<=500

乍一看很简单,只需要设状态函数f(i,j)表示到第i层第j个房间需要的最小花费,转移方程:
\(f(i,j)=min(f(i-1,j),f(i,j-1),f(i,j+1))+a[i][j]\)
其中a[i][j]为当前房间的花费。
初始化
\(f(i,j)=inf\)
\(f(1,j)=a[1][j]|1<=j<=m\)

但是如果每一层这样去转移,无论是从左向右计算还是从右向左计算都有后效性,因为如果从左向右更新,那么计算f(i,j)时用到的f(i,j+1)还没有更新过,会引起错误

解决方法是每一层先从左向右走用f(i,j-1)更新f(i,j),走完这层再从右向左走用f(i,j+1)更新f(i,j),保证了计算时用到的数都不是未知的。

\(Ans=min(f(n,j)|1<=j<=m)\)
我的代码里是从上向下走的,区别不大

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<iostream>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define inf 0x3f3f3f3f
using namespace std;
int n,m;
int a[105][505];
int f[105][505];
void init(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
        }
    }
    for(int i=0;i<=n+1;i++)
        for(int j=0;j<=m+1;j++)
            f[i][j]=inf;
}
void dp(){
    for(int i=1;i<=m;i++)f[n][i]=a[n][i];

    for(int i=n-1;i>=1;i--){
        for(int j=m;j>=1;j--)
            f[i][j]=min(f[i+1][j],f[i][j+1])+a[i][j];//合并右走和下走
        for(int j=1;j<=m;j++)//分开循环防后效
            f[i][j]=min(f[i][j],f[i][j-1]+a[i][j]);//左走
    }

    int ans=inf;
    for(int i=1;i<=m;i++)
        ans=min(ans,f[1][i]);
    printf("%d",ans);
}
int main(){
    init();
    dp();
    return 0;
}

原文地址:https://www.cnblogs.com/de-compass/p/11234809.html

时间: 2024-07-31 13:59:41

cqyz oj | 【训练题】HB办证 P1419 | DP动态规划的相关文章

华为OJ训练题之 比赛情况统计

题目如下: 比赛情况统计 有一个游戏平台,各个参赛队伍(以唯一的TeamID来标识)之间进行单循环的对抗赛,两个队伍之间只举行一场比赛,比赛以得分的多少定胜负.需要完成一个统计赛况的程序,能够随时查询指定队伍的最新赛况:包括胜.平.负的局数,当前总积分以及名次. 说明:循环赛没有全部结束时也可以查询某个队伍的最新赛况 规则说明 比赛判定:两个队伍中得分高的一方为胜者,另一方为负者:得分相同则为平局 积分规则:每一局比赛: 胜者积3分;平局双方各积1分; 负者积0分 排名规则:按照当前总积分的高低

nyist oj 36 最长公共子序列 (动态规划基础题)

最长公共子序列 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 咱们就不拐弯抹角了,如题,需要你做的就是写一个程序,得出最长公共子序列. tip:最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列. 输入 第一行给出一个整数N(0<N<100)表示待测数据组数 接

华为OJ训练 之 括号配对数目问题

题目如下 括号配对问题 输入n个括号,输出能组合的n个括号组合,例如-- 输入1时,只有()一种: 输入2时,有()()和(())两种: 输入3时,有()()(),()(()),(())(),(()())和((())),共5种. 输入4时有14种..依次类推. 我想到的笨方法,类推找规律,因为我相信这个肯定有个公式的.找了好一会.没总结出来,于是翻书,因为印象中看过类似的题. 然后找到了公式.哈哈. import java.util.Scanner; public class Main { pu

nyist oj 17 单调递增最长子序列 (动态规划经典题)

单调递增最长子序列 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 求一个字符串的最长递增子序列的长度 如:dabdbf最长递增子序列就是abdf,长度为4 输入 第一行一个整数0<n<20,表示有n个字符串要处理 随后的n行,每行有一个字符串,该字符串的长度不会超过10000 输出 输出字符串的最长递增子序列的长度 样例输入 3 aaa ababc abklmncdefg 样例输出 1 3 7 来源 经典题目 动态规划的经典题目:好像还有好几种解法,我现在研究的

light oj 1422 - Halloween Costumes (区间dp)

1422 - Halloween Costumes PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB Gappu has a very busy weekend ahead of him. Because, next weekend is Halloween, and he is planning to attend as many parties as he can. Since it's Ha

OJ刷题常用的4中基本输入形式

初到OJ网站上刷题,输入形式就是我们要考虑的问题.通过自己的一些摸索,OJ题目的输入形式大体上无外乎4种.下面就详细介绍: 1 输入数据文件中,第一行数据标明了测试数据的数目: 2 输入数据文件中,有标明输入结束的数据 3 输入数据文件中,测试数据一直到文件尾 4 没有输入数据 第1中情形的处理方法: //int i,kase scanf("%d",&kase); for(i=1;i<=kase;i++) { //处理第i中情况 } ...................

Orz_panda cup I题 (xdoj1117) 状压dp

Orz_panda cup I题 (xdoj1117)  状压dp 1117: Insert Orz Pandas 时间限制: 2 Sec  内存限制: 128 MB提交: 15  解决: 5[提交][状态][讨论版] 题目描述 Orz panda emotion is a famous emotion in XDU/ACM-ICPC QQ groups.Big Big Xi loves to create new Orz panda emotions.Now he has a matrix w

逻辑训练题

1 , 逻辑思维训练题:凶手是谁? 有一个女明星被杀害了,警察抓住两个嫌疑犯,但不能肯定他们谁是凶手.于是警察就展开了调查,发现这个女明星生前很喜欢收藏鞋子,她的鞋箱被翻乱后被凶手放好,警察发现她有八十双鞋子,红箱子有红色和绿色的鞋子各二十双,绿色箱子有红色和绿色的鞋子各二十双,这些鞋子摆的很整齐.警察问两个嫌疑犯你们谁是红绿色盲,甲说:"乙是红绿色盲."聪明的你能猜出请是凶手吗? > > > 分析过程及答案的请往下看 > > > 参考答案: 甲是凶

POJ1141 Brackets Sequence (dp动态规划,递归)

本文出自:http://blog.csdn.net/svitter 原题:http://poj.org/problem?id=1141 题意:输出添加括号最少,并且使其匹配的串. 题解: dp [ i ] [ j ] 表示添加括号的个数, pos[ i][ j ] 表示 i , j 中哪个位置分开,使得两部分分别匹配. pos [ i ][ j ] 为-1的时候,说明i, j 括号匹配. 初始值置dp [ i ] [ i ]  = 1; 如果只有一个括号,那么匹配结果必然是差1. 首先判断括号是