学习日记—动态规划

动态规划学习笔记:

一、什么是动态规划

  动态规划及DP(Dynamic Programming)是⼀种分阶段求解决策问题的数学思想,它通过把原问题分解为简单的⼦问题来解决复杂问题。即通过将大问题划分为小问题,将小问题求解后一步步影响后面其他次小问题而达到全局最优解的一个过程

二、动态规划的核心思想

  将大问题划分为小问题进行解决,从而一步步获取最优解的处理算法。其与分治相似,但不同的是分治不依求上一个问题的解,各个小问题的解独立存在,但动态规划不是

三、典型例题

  数字三角形(蓝桥杯2020年省赛真题)

    1.题目描述

             

     如上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。路径上的每一步只能从一      个数走到下一层和它最近的左边的那个数或者右 边的那个数。此外,向左下走的次数与向右下走的次数相差不能超过1。

    输入描述

      输入的第一行包含一个整数N(1≤N≤100),表示三角形的行数。下面的2~N+1行给出数字三角形。数字三角形上的数都是0至100之间的整数。

    输出描述

      输出一个整数,表示答案。

    2.分析

      翻译题目:给你一个三角形,让你找一条从起点开始一直往下面相邻的两个方向延申将途径的数字相加而数字和最大的路径。注:本题不求路径具体为何只求路径上数字和最大的那个数。

      我刚一看到题目表示这怎么做呀?根本不会,百度一下发现要用动态规划,那我们用动态规划的角度解析一下这个题:首先,我们可以用一个二维数组存一下这个三角形,操作参考杨辉三角,然后,到了重头戏我们要怎么处理或者说怎么通过运算得到结果呢?经过观察我们发现要使数字总和最大那路径上的每个值都尽量大这不废话吗由此我们可得一下状态转移方程:

            设:D(i,j)为第i行第j列的那个数字,MaxSum(i,j)为从D(i,j)开始到底边的最大和

            则:MaxSum(i,j)=D(i,j) (i==N)

              MaxSum(i,j)=MAX(MaxSum(i+1,j),MaxSum(i+1,j+1))+D(i,j)

        那我们照这个写一下,写完长这样:

复制代码
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll N=105;
 5 ll D[N][N],n; 
 6 ll MaxSum(ll i,ll j){//状态转移方程递归解决 
 7     if(i==n)return D[i][j];
 8     ll x=MaxSum(i+1,j),y=MaxSum(i+1,j+1);
 9     return max(x,y)+D[i][j];
10 }
11 int main(){
12     cin>>n;
13     for(int i=1;i<=n;i++){
14         for(int j=1;j<=i;j++)cin>>D[i][j];
15     }
16     cout<<MaxSum(1,1);//此处是求从顶点到底边数字和最大是多少,即结果 
17     return 0;
18 }
19 //码风彪悍,凑合看一下吧(逃 
复制代码

        写完一看,结果是能算出来但时间复杂度O(2^n),这n要是是100,按照目前人类的技术算到50亿年后的太阳爆炸都算不出来,那只能降低一下时间复杂度,通过观察我们发现时间复杂度怎么高主要是因为重复的计算,想了一下之前解决递归重复计算的方法都是记忆化,但用在动态规划上行吗?回答是肯定的。那我们修改一下代码吧。修改完的代码长这样:

复制代码
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll N=105;
 5 ll D[N][N],n,maxsum[N][N];//数据存放数组 
 6 ll MaxSum(ll i,ll j){
 7     if(i==n)return D[i][j];
 8     else if(maxsum[i][j])return maxsum[i][j];//有就直接返回,不计算了 
 9     ll x=MaxSum(i+1,j),y=MaxSum(i+1,j+1);
10     maxsum[i][j]=max(x,y)+D[i][j];//计算完后记录一下 
11     return maxsum[i][j];
12 }
13 int main(){
14     cin>>n;
15     for(int i=1;i<=n;i++){
16         for(int j=1;j<=i;j++)cin>>D[i][j];
17     }
18     cout<<MaxSum(1,1);
19     return 0;
20 }
21 //码风彪悍,凑合看一下吧(逃 
复制代码

        不一样的地方已经标注出来了。

        这是本人第一次写博客,写的不好的地方望海涵,有错误的地方欢迎指正。

posted @   2009cqr  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
点击右上角即可分享
微信分享提示