注:2019-09-13,MOOC北大程序设计与算法第六周,动态规划2
不建议新手看我的c++ 版本,怕误导人…
1最长上升子序列问题【回顾复习】
1:maxlen[n],状态数组,最终会记录最长上升子序列的数值
int main() {
const SIZE 101;
int len1[SIZE];
int n;
int maxlen[n];
cin >> n;
cout << "你所选择的数组长度是:" << n << "请输入 -" << n << "个数字放入数组" << endl;
for (int i = 0; i < n; i++) {
cin >> len1[i];
maxlen[i] = 1;
}
cout << "输入完毕,开始计算 .\n";
for (int i = 1; i < n; i++)
for (int k = 0; k < i, k++)
if len1[k] < len1[i]
maxlen[i] = max(maxlen[i], maxlen[k]) + 1;
return 0;
}
一年半之前刚学程序语言碰上递归,到4399玩了半小时汉诺塔才通关。到现在这么长时间过去了。递归主要是表述想法的时候比较简便,真正理解后其实也很好懂,但是实际应用还是递推。
2,最长公共子序列
给定两个字符串,找到共有的两个最长排列字符
例如 “abcdgfr”和 “acklrdg” 就是 “acdg” 输出值为4
没看课程,自己先想了一会,这个状态构造没想出来。。。有点菜
主要碰到遍历问题,却没想到用二维数组来解决
解决方案:
1,状态构建: 二维数组(方阵)total,长度为最大的字符串长度
2,状态转移:田字格,右下角与其他三格之间的转换,注意转换只能是相邻之间,我之前想的用一位数组就是遇到了这个问题,无法进行转换
python:
import numpy as np
strx = ['abcdgrf', 'acklrdg']
len1 = len(strx[0])
len2 = len(strx[1])
matrix = np.zeros(len1+1, len2+1])
matrix = matrix.astype(np.int8).tolist()
for i in range(1, len1+1):
for k in range(1, len2+1):
if strx[0][i-1] == strx[1][k-1]:
matrix[i][k] = matrix[i-1][k-1] + 1
else:
matrix[i][k] = max(matrix[i][k-1], matrix[i-1][k]
print(matrix[len1][len2])
c++
本想用中文字符串,但似乎c++ 遍历中文字符串不太OK,毕竟还是初学,暂时用字母吧:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string str1 = "abcfgry";
string str2 = "abfgcyrlj";
const int len1 = str1.size();//得到最大字符串长度
const int len2 = str2.size();
// cout << len1 << endl;
int matrix[len1 + 1][len2 + 1];
// 初始化其中一个字符串长度为0时候的矩阵元素为0
int i, j;
for (i = 0; i <= len1; i++)
matrix[i][0] = 0;
for (j = 0; j <= len2; j++)
matrix[0][j] = 0;
for (int i = 1; i <= len1; i++)
for (int j = 1; j <= len2; j++)
if (str1[i - 1] == str2[j - 1])
matrix[i][j] = matrix[i - 1][j - 1]+1;
else
matrix[i][j] = max(matrix[i][j - 1], matrix[i - 1][j]);
cout << matrix[len1][len2];
return 0;
}
总结
动态规划问题核心就是 1 问题拆解 2,状态构建 3,状态转移