想深入学习下动态规划算法,关于动态规划的基础知识等,另开一贴记录。
先做一道简单的动态规划题,建立感性的认识。
数字三角形,这是一道树形动态规划题,很简单,就从这开始吧。
题目如下:
http://leetcode.com/onlinejudge#question_120
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
For example, given the following triangle
[ [2], [3,4], [6,5,7], [4,1,8,3] ]
The minimum path sum from top to bottom is 11
(i.e., 2 + 3 + 5 + 1 = 11).
Note:
Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.
data[4][4]=
{
{2},
{3,4},
{6,5,7},
{4,1,8,3}
}利用辅助空间dp[i][j],保存以data[i][j]为顶点,走到底边的minimum path sum。
将辅助空间dp中底边的值初始化为data底边的值,其他元素置零
然后自底向上计算。公式如下:
dp[i][j]=data[i][j]+max{dp[i+1][j],dp[i+1][j+1]};
最后dp[0][0]即所求minimum path sum。
当然也可以自顶向下计算,只要考虑好该节点由上一层哪个节点过来就可以了。另外在计算完dp后,还要遍历一下dp的底层,取出最小值,即minimum path sum。
LeetCode代码如下:
class Solution {
public:
int min(int a,int b)
{
return a<b?a:b;
}
int minimumTotal(vector<vector<int> > &triangle)
{
int N=triangle.size();
int l,m;
int **dp=new int*[N];
for(l=0;l<N;l++)
{
dp[l]=new int[N];
}
for(l=0;l<N;l++)
for(m=0;m<N;m++)
dp[l][m]=0;
for(m=0;m<N;m++)
{
dp[N-1][m]=triangle[N-1][m];
}
for(l=N-2;l>=0;l--)
{
for(m=0;m<=l;m++)
{
dp[l][m]=triangle[l][m]+min(dp[l+1][m],dp[l+1][m+1]);
}
}
return dp[0][0];
//for(l=0;l<N;l++)printf("%d %d %d %d",triangle[0][0],N,N,N);
}
};
以例子来运行,每次循环后dp中元素的值。第一组为data数据。如下:
碰到想到的问题:
1、C中多维数组作形参的形式如下:
f(int (*a)[N])
该种形参只能传入数组名的实参,不能传入用二级指针+malloc动态生成的二维数组。
另外多维数组只有第一维能通过初始化参数自动获得。
一维数组如下:
f(int a[])
2、C和C++创建动态数组
C:
int **dp=(int**)malloc(N*sizeof(int*));
for(l=0;l<N;l++)
{
dp[l]=(int*)malloc(N*sizeof(int));
}
C++:
int **dp=new int*[N];//此处new出1个10维的指针数组,见3.
for(l=0;l<N;l++)
{
dp[l]=new int[N];
}
3、指针数组和数组指针
int (*p)[10];//声明的是p,是一个指针,指向的是一个10维的整型数组。---数组指针
int *p[10];//声明的是p[10],是一个数组,是10个指向整形指针的数组。---指针数组