#include <iostream> using namespace std; void maxDp(const int nums[], int dp[], const int n) { for (int i = 1; i < n ; i++) { for (int j = 0; j < i ; j++) { if (nums[i] > nums[j]) { dp[i] = max(dp[i], dp[j] + 1); } } } } int main() { int n; cin >> n; int nums1[n];//正序排 int nums2[n];//倒序排 int dp1[n];//正dp int dp2[n];//倒dp //读数顺便初始化数组 for (int i = 0; i < n; i++) { cin >> nums1[i]; dp1[i] = 1; dp2[i] = 1; nums2[n - i - 1] = nums1[i]; } maxDp(nums1, dp1, n); maxDp(nums2, dp2, n); int maxNum = 0; for (int i = 0; i < n ; i++) { if (maxNum < dp1[i] + dp2[n - i - 1] - 1 ) { maxNum = dp1[i] + dp2[n - i - 1] - 1; } } cout << n - maxNum << endl; }
这题是最长子序列的衍生问题,只要把数组反过来再做一个dp数组,然后找2头加起来队列最大的那个就没毛病了。
附上最长子序列笔记。
2.1最长递增子序列
2.1.1问题描述:
- 在一个数组中选取某些元素,元素之间保持数组原有顺序并保持递增
2.1.2 dp[i]的含义
- 以num[i]为结尾的最长递增子序列的长度
2.1.3 递推公式
- if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1);
2.1.4 dp数组的初始化
- dp[i] = 1;默认为自身
2.1.5 遍历顺序(2层for循环)
- i从1开始小到大遍历(dp[0] = 1)
- j从小到大或者从大到小都可以,默认从小到i就可以了
for (int i = 1; i < nums.size(); i++) { for (int j = 0; j < i; j++) { if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1); } if (dp[i] > result) result = dp[i]; // 取长的子序列}
2.1.6 结果
- dp数组的最大值,可以在dp遍历的时候求即可