动态规划立体匹配代码_经典算法系列:动态规划

531f5035a6d0b8409ade742473800bce.png

​动态规划是算法里一个很重要的思想,在腾讯,网易等各大公司的笔试面试中经常遇到。

动态规划的思想是将一个问题分解为若干个子问题,对每个子问题求最优解,前一个子问题的最优解,为下面的子问题提供了有效信息,依次解决子问题,最后一个子问题就是初始问题的最优解。动态规划应用于子问题重叠的情况,子问题的划分是通过递归实现。为了避免子问题的重复计算,保证每个子问题只求解一次,会将解保存在数组中

75939f8a85bcfd24a24af9efb93cdf2f.png

动态规划的基本步骤如下:

1.刻画一个最优解的结构特征;

2.递归定义最优解的值;

3.计算最优解的值,通常采用自底向上的方法。

76ba5ffd647d09199b6bb6dac9252ee5.png

那么,什么时候采用动态规划的思想呢?动态规划的问题一般有两个特征:(1)最优子结构。如果一个问题的最优解包含子问题的最优解,那么该问题就具有最优子结构;(2)重叠子问题。如果递归算法反复计算相同的子问题,那么该问题具有重叠子问题。如果在递归的每一步都生成新的子问题,那么要用分治法解决。

我们来看下面这道2017年腾讯实习生笔试题:

74ef86da3539cc9d931b3b5b8d25527b.png

求解最长回文串,即正序和逆序一样,可以将s的逆序表示出来,求逆序s和正序s的最长公共子序列,该最长公共子序列即最长的回文串。那什么是最长公共子序列呢?

1bda829f5024f34baef7f1f28e05880b.png

96bdfbdcb8faae2951694fc288beb29f.png

接下来,该问题就转化成了求最长公共子序列的问题,而求解此类问题,就用到了动态规划。求最长公共子序列,思想如下:

fe3565bd51676b5f4f33fb978b2a7221.png

递推式如下,c[i,j]表示(x1,x2....xi) 和 (y1,y2...yj) 的最长公共子序列的长度

cea6ace6e6ce530ce12ea479c3bdddd8.png

如果不采用动态规划,只用递归,代码如下:

2dc0f6bb2ae004ee3388981768522c6b.png

提交运行后会显示超时运行。因为子问题被重复计算,LCS(s,i-1,rs,j)和LCS(s,i,rs,j-1)都包含了子问题LCS(s,i-1,rs,j-1)。因此下面采用动态规划来解决。

e40c42805b9d107df3a116f4163d9faa.png

b912329c49e83777c8caa3aa37ded9f3.png

在上述代码中,D[i][j]代表大小为i+1*j+1的数组,为什么要+1呢?这里用0表示无元素,所以初始化阶段,数组值如下:

44671c50307fd923a58d9ffdbe696d76.png

然后循环,依次把二维数组填满即可。

总结一下,所谓动态规划,就是在解决具有最优子结构和重复子问题两种特性的问题时,把求解子问题的递归方法改成用数组保存结果的方法,数组的值不再用递归求得,而是用递推公式求得,然后就可以直接查表实现。

参考来源:

[1] 算法导论

[2]https://www.cnblogs.com/hapjin/p/5572483.html

[3]http://blog.csdn.net/baidu_28312631/article/details/47418773

本文所有代码均为本人编写并经过测试,如有错误或问题,欢迎留言或私信指正。

274317e67c80dd328959b56547d2f5bc.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是双目立体匹配算法SGM的实时代码: ``` #include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; const int max_image_size = 960; const int max_disparity = 64; const int P1 = 5; const int P2 = 70; const int penalty_scale = 10; const int uniqueness_ratio = 15; const int speckle_window_size = 100; const int speckle_range = 32; int main(int argc, char** argv) { if(argc != 3) { cout << "Usage: ./sgm_stereo left_image right_image" << endl; return -1; } Mat imgL = imread(argv[1], IMREAD_GRAYSCALE); Mat imgR = imread(argv[2], IMREAD_GRAYSCALE); if(imgL.empty() || imgR.empty()) { cout << "Error: Could not open or find the images" << endl; return -1; } int width = imgL.cols; int height = imgL.rows; if(width > max_image_size || height > max_image_size) { cout << "Error: Image size too large" << endl; return -1; } int min_disparity = 0; int max_disparity = 64; Mat disparity_map = Mat::zeros(height, width, CV_8UC1); for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { int min_cost = INT_MAX; int best_disparity = min_disparity; for(int d = min_disparity; d < max_disparity; d++) { int sum = 0; int count = 0; for(int dy = -1; dy <= 1; dy++) { for(int dx = -1; dx <= 1; dx++) { int xl = x + dx; int xr = x + dx - d; if(xl < 0 || xl >= width || xr < 0 || xr >= width) { continue; } int diff = abs((int)imgL.at<uchar>(y+dy, x+dx) - (int)imgR.at<uchar>(y+dy, xr)); sum += diff; count++; } } int cost = sum / count; if(d > min_disparity) { int diff = abs(d - best_disparity); cost += (diff == 1) ? P1 : (P1 + (diff - 1) * P2); } if(cost < min_cost) { min_cost = cost; best_disparity = d; } } disparity_map.at<uchar>(y, x) = best_disparity; } } Ptr<StereoSGBM> stereo = StereoSGBM::create(min_disparity, max_disparity, penalty_scale, 8 * imgL.channels() * speckle_window_size * speckle_window_size, 32 * speckle_range, uniqueness_ratio, StereoSGBM::MODE_SGBM_3WAY); stereo->compute(imgL, imgR, disparity_map); namedWindow("Disparity Map", WINDOW_NORMAL); imshow("Disparity Map", disparity_map); waitKey(0); return 0; } ``` 需要注意的是,此代码只是SGM算法的实现之一,针对不同的场景和需求,实现方式可能会有所不同。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值