C:动态规划算法详解及走方格问题


概念

动态规划是运筹学中用于求解决策过程中的最优化数学方法。当然,我们在这里关注的是作为一种算法设计技术,作为一种使用多阶段决策过程最优的通用方法

基本思想

基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了实用的信息。

在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其它局部解。依次解决各子问题,最后一个子问题就是初始问题的解。

  • 动态规划解决的问题多数有重叠子问题这个特点。为降低反复计算。对每个子问题仅仅解一次,将其不同阶段的不同状态保存在一个二维数组中。
  • 动态规划算法与分治法最大的区别是:适合于用动态规划法求解的问题,经分解后得到的子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解)。

动规解题的一般思路:

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

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

  2. 确定状态

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

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

    以“方格”为例,边界状态就是第一行与第一列,值就是1。

  4. 确定状态转移方程

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

能用动规解决的问题的特点:

  1. 问题具有最优子结构性质。如果问题的最优解所包含的 子问题的解也是最优的,我们就称该问题具有最优子结 构性质。
  2. 无后效性。当前的若干个状态值一旦确定,则此后过程的演变就只和这若干个状态的值有关,和之前是采取哪种手段或经过哪条路径演变到当前的这若干个状态,没有关系。
  3. 有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到(该性质并非动态规划适用的必要条件,可是假设没有这条性质。动态规划算法同其它算法相比就不具备优势)。

问题描述:

小明从A点要去B点,请问有多少种不同的路线?规则是只能向下和向右走。

在这里插入图片描述

思绪:

  • 典型的动归问题,假设B在A的右边,此时只有一条路线;B在A的下面,也只有一条路线;
  • 然后慢慢累加,如下图所示!

在这里插入图片描述

问题扩展:

此时在A到B的路程中有一柱子挡着(柱子不能被翻越)。请问有多少种不同的路线?

思绪

  • 同上所述,不考虑柱子占据的位置,慢慢累加!

在这里插入图片描述

代码如下:

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
#include<stdlib.h>

int main(){
	int a[10][10] = { 0 };
	int x, y;
	int x1, y1;
	int i, j;

	printf("请输入表格的行与列:");
	scanf("%d%d", &x, &y);
	printf("请输入柱子的坐标:");
	scanf("%d%d", &x1, &y1);//可以在图中设置柱子
	for (i = 1; i <= x; i++){
		for (j = 1; j <= y; j++){
			if (i == x1 && j == y1){//如果是柱子则不计数直接跳过
				continue;
			}
			if (i == 1 && j == 1){
				a[i][j] = 1;
			}
			else{
				a[i][j] = a[i - 1][j] + a[i][j - 1];
			}
		}
	}
	printf("共有%d种不同的路线 ", a[x][y]);

	system("pause");
	return 0;
}

代码生成图:
在这里插入图片描述
在这里插入图片描述

问题升级:(类似于数塔问题)

还是由A走到B,但每个格子对应有数字,求A(5)走到B(6),数字最大为多少?

在这里插入图片描述

思绪:

  • 同上所述,先确定边界状态!确定里面的状态需要用与他相临(上方,左方)较大边界与他相加,确定自身状态!
    在这里插入图片描述
  • 最终确定下来的每个格子状态为下图所示:
    在这里插入图片描述

代码如下:

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
#include<stdlib.h>

int main(){
	int a[5][5] = { { 0, 0, 0, 0, 0 }, 
					{ 0, 5, 18, 4, 20 },
					{ 0, 22, 15, 9, 10 }, 
					{ 0, 14, 16, 12, 21 }, 
					{ 0, 19, 8, 11, 6 } };
	int i, j;
	
	for (i = 1; i <= 4; i++){
		for (j = 1; j <= 4; j++){
			if (a[i-1][j] > a[i][j-1]){
				a[i][j] += a[i-1][j];
			}
			else{
				a[i][j] += a[i][j - 1];
			}
		}
	}
	printf("数字最大为%d\n", a[4][4]);

	system("pause");
	return 0;
}

代码生成图:
在这里插入图片描述

  • 8
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
SGBM算法中的动态规划部分是指SGM算法(Semi-Global Matching)的实现。在SGBM算法中,首先通过计算代价图来获取初始的视差图。然后,利用动态规划的思想对初始视差图进行优化,以得到更准确的视差图。 动态规划是一种优化问题的常用方法,它通过将问题分解为子问题,并利用子问题的最优解来求解整个问题的最优解。在SGBM算法中,动态规划被用于对每个像素的视差值进行优化。 具体来说,SGBM算法中的动态规划部分包括以下几个步骤: 1. 定义代价函数:根据图像的亮度差异等因素,定义一个代价函数来衡量不同视差值的匹配程度。 2. 计算代价图:对于每个像素,计算其与邻域像素的代价值,并将这些代价值组成一个代价图。 3. 动态规划优化:利用动态规划的思想,从左到右和从上到下遍历代价图,通过比较当前像素与其左侧和上方像素的代价值,选择最小的代价值作为当前像素的最优视差值。 4. 反向传播:从右下角开始,从右到左和从下到上遍历代价图,通过比较当前像素与其右侧和下方像素的代价值,进一步优化当前像素的最优视差值。 5. 视差平滑:为了进一步提高视差图的质量,可以对最终的视差图进行平滑处理,以减少噪声和不连续性。 通过以上步骤,SGBM算法能够对初始视差图进行优化,得到更准确的视差图。这样可以提高立体匹配的效果,使得物体的深度信息更加准确可靠。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值