2016级算法第二次练习赛——AlvinZH掉坑系列(动态规划)

本文介绍了动态规划问题的解题思路,包括如何将原问题分解为子问题,确定状态和初始状态值,以及状态转移方程。通过分析AlvinZH在不同题目中遇到的问题,如在宝藏迷宫中寻找最大金币数,以及如何优化算法避免重复计算,深入探讨了动态规划在实际问题中的应用。
摘要由CSDN通过智能技术生成

动态规划问题解题思路

1. 将原问题分解为子问题

  •     把原问题分解为若干个子问题,子问题和原问题形式相同或类似,只不过规模变小了。子问题都解决,原问题即解决(数字三角形例)。
  •     子问题的解一旦求出就会被保存,所以每个子问题只需求 解一次。

    2.确定状态

  •     在用动态规划解题时,我们往往将和子问题相关的各个变量的一组取值,称之为一个“状 态”。一个“状态”对应于一个或多个子问题, 所谓某个“状态”下的“值”,就是这个“状 态”所对应的子问题的解。
  •     所有“状态”的集合,构成问题的“状态空间”。“状态空间”的大小,与用动态规划解决问题的时间复杂度直接相关。 在数字三角形的例子里,一共有N×(N+1)/2个数字,所以这个问题的状态空间里一共就有N×(N+1)/2个状态。

    整个问题的时间复杂度是状态数目乘以计算每个状态所需时间。在数字三角形里每个“状态”只需要经过一次,且在每个状态上作计算所花的时间都是和N无关的常数。

    3.确定一些初始状态(边界状态)的值

    以“数字三角形”为例,初始状态就是底边数字,值就是底边数字值。

    4. 确定状态转移方程

     定义出什么是“状态”,以及在该“状态”下的“值”后,就要找出不同的状态之间如何迁移――即如何从一个或多个“值”已知的 “状态”,求出另一个“状态”的“值”(递推型)。状态的迁移可以用递推公式表示,此递推公式也可被称作“状态转移方程”。

H AlvinZH掉坑里了

时间限制:1000ms   内存限制:65536kb

题目描述

AlvinZH掉进坑里了。

幸运的是,这坑竟然是宝藏迷宫的入口。迷宫为n*m的矩阵,每个格子里有一定数目的金币,AlvinZH现在位于迷宫的左上角,而出口在迷宫的右下角,而且AlvinZH只能向下或向右前进。

AlvinZH想在出去的同时,能取得最大数目的金币,快来帮他计算一下能取得的最大金币数吧!

输入

输入包含多组数据。

每组数据第一行为两个正整数n、m(2≤n,m≤500)。

接下来n行,每行m个正整数,为该格子的金币数,数字以空格隔开。

输出

对于每组数据,输出一行,为能取得的最大金币数(答案在int范围内)。

输入样例

3 3
1 1 3
3 3 3
3 1 1

输出样例

11

解题思路

简单DP。
用dp[i][j]表示走到点(i,j)所能获得的最大金币数,则可以得到状态转移方程  dp[i][j]=max{dp[i-1][j],dp[i][j-1]}+B[i][j]
这样,初始化dp数组为一个极小值,然后通过循环,来更新到达每个位置所能获得的最大金币数就行了,最后结果就是dp[n][m].

    
    
     
      
    
    

    
    
     
      
    
    

示例代码

#include<cstdio>
#include<cstring>
int B[507][507];//记录每个位置的金币数
int dp[507][507];//用于存储到达ij点处所能获得的最大金币数

int max(int i,int j)
{
    if(dp[i-1][j]>dp[i][j-1])
        return dp[i-1][j];
    else
        return dp[i][j-1];
}
int main()
{
    int m,n;
    while(~scanf("%d%d",&n,&m))
    {
        memset(dp,-100,sizeof(B));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&B[i][j]);
        dp[1][1]=B[1][1];
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(dp[i][j]<0)
                    dp[i][j]=max(i,j)+B[i][j];
        printf("%d\n",dp[n][m]);
    }
}

I AlvinZH又掉坑里了

时间限制:1000ms   内存限制:100000kb

题目描述

AlvinZH又掉进坑里了。

幸运的是,这坑竟然还是宝藏迷宫的入口。迷宫为n*m的矩阵,每个格子里有一定数目的金币,AlvinZH现在位于迷宫的左上角,而出口竟然就在入口的位置,不过有了上次的经历,AlvinZH知道这里面有很多金币,他决定溜一圈再出去。他先从左上角走到右下角,他只能向下或向右前进;然后从右下角走回左上角,这次他只能往上或往左走。

AlvinZH想在出去的同时,能取得最大数目的金币,快来帮他计算一下能取得的最大金币数吧!

请注意内存限制。

输入

输入包含多组数据。

每组数据第一行为两个正整数n、m(2≤n,m≤200)。

接下来n行,每行m个正整数,为该格子的金币数,数字以空格隔开。

输出

对于每组数据,输出一行,为能取得的最大金币数(答案在int范围内)。

输入样例

3 3
1 1 3
3 3 3
3 1 1

输出样例

16

解题思路(来自助教http://www.cnblogs.com/AlvinZH/p/7840604.html

难题。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值