题目:
给定一个整数序列,输出它的最长递减(注意不是“不递增”)子序列。
输入包括两行,第一行包括一个正整数N(N<=1000),表示输入的整数序列的长度。第二行包括用空格分隔开的N个整数,整数范围区间为[-30000,30000]。
输出为一行,最长递减子序列的结果,数字间用空格分隔(测试case中只会有一个最长递减子序列)。
样例输入
8 9 4 3 2 5 4 3 2
样例输出
9 5 4 3 2
思路:这道题不能使用优化的最长上升子序列,因为它要记录路径,优化的最长上升子序列dp[i]表示的是长度为i+1的上升子序列中末尾元素的最小值,并不是路径。所以还是用O(n²)的算法;
dp[i]表示到前i个元素的最大长度。如果a[i]>a[j],dp[i]=max(dp[i],dp[j]+1)。j从1到i;
递减序列和递增相同。
每次记录当前最优解的上一个节点,最后用栈构造最优解。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a[1005], dp[1005] , ans[1005] = { 0 }, n, res = 1;//ans记录路径
cin >> n;
fill(dp + 1, dp + n + 1, 1);//最小长度至少为1
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++)
{
for (int j = 1; j < i; j++)
{
if (a[j] > a[i]&&dp[j]+1>dp[i])
{
dp[i] = dp[j] + 1;
ans[i] = j;//记录上一个点坐标
}
}
if (dp[i] > dp[res])
res = i;
}
//cout << dp[res];
stack<int> Q;
for (int i = res; i != 0; i = ans[i])
Q.push(a[i]);
cout << Q.top();
Q.pop();
while (!Q.empty())
{
cout << " " << Q.top();
Q.pop();
}
return 0;
}