从只有 3 个有效移动的数组中制作最大长度升序子数组
Posted
技术标签:
【中文标题】从只有 3 个有效移动的数组中制作最大长度升序子数组【英文标题】:Making Maximum Length Ascending Sub array from an array with only 3 valid moves 【发布时间】:2019-09-04 16:04:24 【问题描述】:我需要用 DP 解决这个问题,问题是: 我们有一个数组,我们想在两个条件下创建一个最大大小的升序子数组:
-
我们可以从左到右遍历数组一次。
我们只有两个有效的移动来创建这个子数组:
我们可以忽略遍历中数组中的下一个元素
我们可以将下一个元素放在数组的末尾或开头,并且该数组必须按升序排列
例如:
输入:arr[ ] = 0 , 3 , 10 , 7 , 6 , 5 , 14
输出:5
子数组是5 , 6, , 7 , 10 , 14
本例的解决方案是,从 10 开始,然后将 7 放在左侧,然后将 6 和 5 放在左侧,然后将 14 放在 10 的右侧
这意味着我们可以通过这个条件从左到右扩展数组
【问题讨论】:
【参考方案1】:这是一个经典的 dp 问题,用自上而下的方法很简单。
让我们定义我们的状态 dp[c][dec][inc] - 我们现在正在查看位置 c 的元素,我们构建的序列后面的元素是位置 dec,并且前面的元素序列在位置 inc。
所以现在我们可以遍历到:
dp[c+1][dec][inc] 通过跳过当前元素 dp[c+1][c][inc] 将当前元素放在后面(仅当 a[c] dp[c+1][dec][c] 将当前元素放在前面(仅当 a[c] >= a[inc] 时有效)示例代码(C++):
const int n = 7;
int a[] = 0, 0, 3, 10, 7, 6, 5, 14;
int dp[n+1][n+1][n+1];
int solve(int c, int dec, int inc)
if(c > n)return 0;
if(dp[c][dec][inc] != -1)return dp[c][dec][inc];
dp[c][dec][inc] = solve(c+1,dec,inc); //skip element
if(inc==0 && dec==0) //if our sequence is empty, try appending element to sequence
dp[c][dec][inc] = max(dp[c][dec][inc], 1 + solve(c+1,c,c));
else if(a[c] >= a[inc])//we can extend our array [dec, ..., inc] because current element can be put to front
dp[c][dec][inc] = max(dp[c][dec][inc], 1 + solve(c+1,dec,c));
else if(a[c] <= a[dec])//we can extend our array [dec, ..., inc] because current element can be put to back
dp[c][dec][inc] = max(dp[c][dec][inc], 1 + solve(c+1,c,inc));
return dp[c][dec][inc];
int main()
memset(dp, -1, sizeof dp);
cout<<solve(1,0,0);
复杂度 O(n^3)
【讨论】:
以上是关于从只有 3 个有效移动的数组中制作最大长度升序子数组的主要内容,如果未能解决你的问题,请参考以下文章