关于子序列的问题做个记录
一、最长上升子序列
题目描述剥离,不管时搬箱子还是其他,一般来说,只要符合求后面的值比前面的大的序列长度基本上能套用
LIS解法(1)动态规划
找到序列1 7 3 5 9 4 8最长上升子序列
找到初始化条件&状态转移方程
初始化:对于序列中的每个元素来说,它本身的长度都是1,这是个重要的初始化条件
状态转移方程:对于i和j来说,假设索引i>j,序列为a的话。那么无非有两种情况,如果a[i] > a[j],那么序列的长度dp[j]+1 和dp[i]的值谁大的问题。即 maxLen = max(dp[i],dp[j]+1) ( a[i] > a[j]),注意此时只有a[i] 大于a[j]时才成立,也就是说当索引为i时,比较前 j个元素上升子序列+1 和 以i结尾时最长上升子序列谁大的问题
代码如下:
int boxMaxNum(vector<int> &numInfo)
{
int allBoxNum = numInfo.size();
int maxNum = 0;
int *dp = new int[allBoxNum];
//动态规划值初始化为1
for (int m = 0; m < allBoxNum; m++) {
dp[m] = 1;
}
//状态转移方程实现
for (int i = 0; i < allBoxNum; i++) {
for (int j = 0; j < i; j++) {
if (numInfo[i] > numInfo[j]) {
dp[i] = max(dp[j] + 1, dp[i]);
}
}
maxNum = max(maxNum, dp[i]);
}
for (int k = 0; k < allBoxNum; k++) {
cout << dp[k] << " ";
}
cout << endl;
cout << "max num is:" << maxNum << endl;
delete [] dp;
return maxNum;
}
main函数:
int boxNum;
cin >> boxNum;
if (boxNum <= 0) {
cout << 0 << endl;
}
vector<int> boxInfo;
int numInfo;
for (int i = 0; i < boxNum; i++) {
cin >> numInfo;
boxInfo.push_back(numInfo);
}
int maxNum = boxMaxNum(boxInfo);
cout << maxNum << endl;
输出子序列和最大的上升子序列长度
二、最大上升子序列的和
求最大上升子序列的和的问题 和 求最大上升子序列的长度 理论上时一致的 上面用dp[]来表示最大的长度,同样,也可以用dp[]来表示上升子序列的和,问题可以向下面转化
初始状态: sum[i] = a[i],即每个值的位置的和为 其本身的值,初始值非常重要
状态转移方程:当遍历到 i 位置时,需要不断比较 sum[i] 和 sum[j]+a[i]的大小,与上一题的思路完全一致,唯一变化的是初始值变成每个值自身。一个求的是最长的长度,一个是求累加的和,都用一个额外的数据结构来存储 中间的长度或者和 ,最后做下比较 。相当于说 定义的数据结构sumValue中存储的是 从前到后的之前计算的值
1 7 3 5 9 4 8---当遍历到5的时候,需要从1开始比较
j = 0:比较值sum[i] 和 sum[ j ] + numInfo[i] -------max(5,6)------->6
j = 1:不用比较
j = 2: 比较 sum[ i ] 和sum[ j ] + numInfo[ i ]--------------max(6, 4 (sum[2]) + 5 (numInfo[3]))-----9
依次类推
转移方程: max ( sum[ i ], sum[ j ] + numInfo[ i ] )
当前的和的值 前一个和的值+当前值
代码:
int sumValue[1001];
int getMaxUpSum(vector<int> &numInfo)
{
int maxSumValue = 0;
int Len = numInfo.size();
for (int k = 0; k < Len; k++) {
sumValue[k] = numInfo[k];
}
for (int i = 1; i < Len; i++) {
for (int j = 0; j < i; j++) {
if (numInfo[i] > numInfo[j]) {
sumValue[i] = max(sumValue[ j ] + numInfo[ i ], sumValue[ i ]);
}
}
}
for (int n = 0; n < Len; n++) {
cout << sumValue[n] << " ";
}
return maxSumValue;
}
附上另外一个好的解释:https://www.nowcoder.com/questionTerminal/dcb97b18715141599b64dbdb8cdea3bd