动态规划回顾(一)数字三角形模型

前言

学完动态规划,做题,比赛还是容易卡
想了想原因
1.刷题量还不够
2.还是没吃透里面的思想
所以,准备写点博客,再复习一下动态规划。

数字三角形模型

就是分析二维平面上,通过怎么转移状态,来获取到想要的情况

比如二维平面上,每个点都有大小
求从起点到终点的所有路径中每个点之和的最大值;
这就要分析,每一次怎么转移状态,才能保证是最大的

在动态规划里,考虑状态转移基本上都是分析最后一次的操作怎么进行
在这里插入图片描述
比如我们不能走多余的路,所以从起点到终点只能向右,向下走。
对于红点,能转移到红点的状态有两个,第一个是从上方转移过来,第二个是从左边转移过来,我们对于所有能转移到红点的状态取最大值,就可以保证一直转移的是最大值。(同理最小值也是),最后看转移到终点时,所获得的最大状态是上面。

该模型一般有两类

1.单路径

典型的就是数字三角形本身
传送门
题目大意
写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。

在这里插入图片描述

做法

就单纯的分析一条路径就行,找转移到该点时,最大的路径和
状态表示
f [ i , j ] 表示转移到该点时的最大路径和
状态计算
f[i,j] 可以由 f[i-1,j-1] (左上) 和 f[i-1,j] (右上) 转移过来。
f[i,j] =max(f[i-1,j-1],f[i-1,j])

核心代码
 for(int i=0;i<=n;i++)
		for(int j=0;j<=n;j++) f[i][j]=-0x3f3f3f3f;   //  初始化所有为负无穷,表示不可取
		//  因为该二维平面不是规则的,超过这个三角形的,不可取。
		
	f[1][1]=a[1][1];   //  初始起点
	
	for(int i=2;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			f[i][j]=max(f[i-1][j-1]+a[i][j],f[i-1][j]+a[i][j]); //  用来自左上和右上路径的最大值来转移
		}
	}

经典题目还有 采花生

2.双路径

该模型一般问在 二维平面里怎么走两次,使的路径上的点和最大(不能重复或者让走过路径上的点为0)

这种只能同时走,不能分两次走

分开两次走(贪心):第一次走到(n, n)求出最大值并记录路径令路径上点收益为0后再走一次。
第一次走为局部最优并且也对第二次走造成了影响,第二次走是在第一次影响下所能走的局部最优,不具备“无后效性”,因此分开两次走并不是全局最优解

典型题目 方格取数

题目大意
从A到B只能向下和向右,求走两次的最大值
在这里插入图片描述

做法

一般是一次性走两条路径,注意特判重合的情况,在曼哈顿距离中,当路径长度一样时,当横坐标(纵坐标)一样时,两个路径在该点重合。
状态表示
f [ l e n ] [ i 1 ] [ i 2 ] f[len][i_1][i_2] f[len][i1][i2] 表示路径一共len长,第一个路径的纵坐标为 i 1 i_1 i1,第二个路径的纵坐标为 i 2 i_2 i2
状态计算
对于一条路径来说 该点可以由上方的路径或者左方的路径转移过来,有两种状态
那两个路径一共有四个状态
路径 1 路径2
从上方 从上方
从上方 从左方
从左方 从左方
从左方 从上方

核心代码
for(int len=2;len<=2*n;len++)
    {
        for(int i1=1;i1<=n;i1++)
        {
            for(int i2=1;i2<=n;i2++)
            {
                int j1=len-i1,j2=len-i2;
                if(j1<=n && j1>=1 && j2<=n && j2>=1)  //  保证合法,不出界
                {
                    int v=a[i1][j1];   //  路径1点的大小
                    if(i1!=i2 )
                    {
                        v+=a[i2][j2];   //  如果两个路径点不重合,再加上路径2的点
                    }
                    int &s=f[len][i1][i2];
                    // int dx[]={0,0,-1,-1},dy[]={0,-1,-1,0};
                    for(int k=0;k<4;k++)
                    {
                        s=max(s,f[len-1][i1+dx[k]][i2+dy[k]]);     //  求四个状态的最大值
                    }
                    s+=v;
                }
            }
        }
    }

下一篇
动态规划回顾(二)线性dp

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值