• 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;
    }
    
  • 相关阅读:
    中文繁体简体互换试验
    msSQL2005数据库备份
    C#实现Base64编码与解码
    C#中正则表达式的高级应用
    滚动条样式锦集
    远程MSMQ
    Silverlight+WCF 新手实例 象棋 主界面事件区求和认输(三十二)
    MSSQL 2005 数据库变成可疑状态
    CYQ.Data 轻量数据层之路 华丽升级 V1.3出世(五)
    CYQ.Data 轻量数据层之路 终极升级(二)
  • 原文地址:https://www.cnblogs.com/de-compass/p/11234809.html
Copyright © 2020-2023  润新知