#include <iostream>
#include <stdlib.h>
using namespace std;
#define MAX 10000
int num[MAX], n;
/***********************************************************************************************
经典的O(n^2)的动态规划算法,设num[i]表示序列中的第i个数,
dp[i]表示从1到i这一段中以i结尾的最长上升子序列的长度,初始时设dp[i] = 1(i = 1, 2, ..., len(A))。
则有动态规划方程:dp[i] = max{1, dp[j] + 1} (j = 1, 2, ..., i - 1, 且num[j] < num[i])。
***********************************************************************************************/
int dp[MAX]; //save length
int DP()
{
int maxn = 0;
for(int i=0; i<=n; i++)
{
dp[i] = 1;
for(int j=0; j<i; j++)
{
if(num[i]> num[j] && dp[i] < dp[j] + 1)
dp[i] = dp[j] + 1;
}
if(dp[i] > dp[maxn])
maxn = i;
}
return maxn;
}
/********************************************************************************************
时间复杂度 nlog(n)
开一个栈,每次取栈顶元素top和读到的元素temp做比较,如果temp > top 则将temp入栈;
如果temp < top则二分查找栈中的比temp大的第1个数,并用temp替换它。 最长序列长度即为栈的大小top。
这也是很好理解的,对于x和y,如果x < y且Stack[y] < Stack[x],用Stack[x]替换Stack[y],
此时的最长序列长度没有改变但序列Q的''潜力''增大了。
举例:原序列为1,5,8,3,6,7
栈为1,5,8,此时读到3,用3替换5,得到1,3,8;
再读6,用6替换8,得到1,3,6;再读7,得到最终栈为1,3,6,7。最长递增子序列为长度4。
**********************************************************************************************/
int Greedy()
{
int stack[MAX];
int top = 0;
int tp;
stack[top] = num[0]; /* 第一个元素可能为0 */
for(int i = 1; i<n; i++)
{
int low = 0, high = top;
int mid;
while(low <= high) /* 二分检索栈中比temp大的第一个数 */
{
mid = (low + high)/2;
if(stack[mid] > num[i])
low = mid + 1;
else high = mid - 1;
}
if(low == top + 1) top++;
stack[low] = num[i];
}
return top + 1;
/* 最长序列数就是栈的大小(top+1) 最长上升序列存在stack中*/
}