动态规划算法
本系列算法为动态规划内容,包含背包问题、最长上升子序列、最长公共子序列等常见算法的实现,本人会一边学习一边更新此文章,后续会陆续添加其他算法的实现。
1、最长上升子序列(LIS)
注意:1、这里的子序列是指顺序与原数列一致的上升序列,但不要求它们之间的连续性。
2、 最长上升子序列不唯一,这也是《算法导论》里指出的“动态规划方法通常用来求解最优化问题,它的解为问题的一个最优解(an optimal solution), 而不是最优解(the optimal solution)“
例如有如下整数序列:
num[] = {2 3 8 3 2 4 9 8 10}
最长的子序列为 2 3 4 9 10,也可以是 2 3 4 8 10,但是最大长度都为 5,即他们都是一个最优解。
下面给出基于自底向上的方法实现动态规划解决最长上升子序列的问题。
(1)从前往后计算DP表
int main(void)
{
int i, j, k, n, m;
int max_last_index; //最大上升序列的最后一个元素下表
int num[100];
int DP[100]; //以元素i作为一个上升序列的最后一个元素,DP[i]为其序列长度
int pre_index[100]; //元素i为最后一个元素的最大上升序列中,前一个元素为pre_index[i]
scanf("%d", &n);
for (k = 0; k < n; k++)
{
scanf("%d", &m);
for (i = 0; i < m; i++)
{
scanf("%d", &num[i]);
DP[i] = 1;
pre_index[i] = -1; //初始化为升序长度为1, 前一个元素不存在
for (j = 0; j < i; j++)
{
if ((num[j] < num[i]) && (DP[j] + 1 > DP[i]))
{
DP[i] = DP[j] + 1;
pre_index[i] = j;
}
}
}
for (i = 0; i < m; ++i)
{
printf("%d ", DP[i]);
}
printf("\n");
max_last_index = 0;
for (i = 1; i < m; i++)
{
if (DP[i] > DP[max_last_index])
max_last_index = i;
}
printf("最长升序元素个数:%d\n", DP[max_last_index]);
printf("逆序:%d", num[max_last_index]);
j = max_last_index;
for (i = 1; i < DP[max_last_index]; i++)
{
j = pre_index[j];
printf(" %d", num[j]);
}
printf("\n");
}
return 0;
}
(2)从后往前计算DP表
int main(void)
{
int i, j, k, m, n;
int max_first_index;
int num[100];
int DP[100];
int sub_index[100];
scanf("%d", &n);
for (k = 0; k < n; k++)
{
scanf("%d", &m);
for (i = 0; i < m; i++)
{
scanf("%d", &num[i]);
DP[i] = 1;
sub_index[i] = n;
}
for (i = m - 1; i >= 0; i--)
{
for (j = m - 1; j > i; j--)
{
if ((num[j] > num[i]) && (DP[j] + 1 > DP[i]))
{
DP[i] = DP[j] + 1;
sub_index[i] = j;
}
}
}
for (i = 0; i < m; ++i)
{
printf("%d ", DP[i]);
}
printf("\n");
max_first_index = 0;
for (i = 1; i < m; i++)
{
if (DP[i] > DP[max_first_index])
max_first_index = i;
}
printf("最长升序元素个数:%d\n", DP[max_first_index]);
printf("正序:%d", num[max_first_index]);
j = max_first_index;
for (i = 1; i < DP[max_first_index]; i++)
{
j = sub_index[j];
printf(" %d", num[j]);
}
printf("\n");
}
return 0;
}
时间复杂度和方法(1)一样,只是计算DP表时的顺序不一样。
(3)小结
动态规划:最长上升子序列:http://blog.youkuaiyun.com/chenwenshi/article/details/6027086
动态规划算法学习:http://blog.youkuaiyun.com/nevasun/article/details/6977511
最长上升子序列nlogn算法:http://blog.youkuaiyun.com/dangwenliang/article/details/5728363
#待实现算法
背包问题
最长公共子序列