Date: 2019-9-9
Author: ZLR
Problem: POJ-2533
Degree: ※
Algorithm: LIS
思路:
这是一类初级的动态规划问题,之所以从头开始学这些东西,是因为我深知自己的底层基础不够扎实,保持一个初学者的心态才会让我进步的更快吧,话不多说。来算法。
严格的含义:2,2,2,只取第一个位置的2.
如:1,2,3,4 长度为4
1,2,2,2,3,4 长度也为4
1,2,8,2,2,3,4,5,6 长度便为6(1,2,3,4,5,6)
单纯的LIS甚至可以用暴力来写,但是它的时间复杂度太大,一般都会崩掉
我们可以用DP的思想来解决这个求最长严格递增子序列长度的问题
核心就是二层循环,第一层循环遍历当前数组中的每一个数(依次)
第二层循环就是找当前位置之前的(从i 到当前pos_i-1位置)数之中,
找拥有最长序列的数(且该数比该位置小),比如
数组,1,2,3,4
i = 1
j = 1 dp[1]=1;
i=2;
j=1; dp[2]=2;(1+1)
i=3;
j=1; dp[3]=2;(1+1)
j=2; dp[3]=3;(2+1)
i=4;
…
j=3;dp[4]=4;(3+1)
这个问题的时间复杂度是n^2
也不是太好
所以我们可以用贪心的解决办法来对该问题进行优化
题解:
#include <stdio.h>
#include <algorithm>
#define INF 0x3f3f3f3f
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
int arr[1005];
int dp[1005];
int main()
{
int n;
cin>>n;
int maxn=-1;
for(int i=0;i<n;i++)cin>>arr[i];
fill(dp,dp+n,INF);
for(int i=0;i<n;i++)
*lower_bound(dp,dp+n,arr[i])=arr[i];
cout<<lower_bound(dp,dp+n,INF)-dp<<endl;
return 0;
}