最長上升子序列(LIS)的兩種演算法
方法一:時間複雜度O(n^2)
狀態轉移方程為dp[I]=max(dp[i],dp[j]+1) (j<i);
很好理解:假設有一個序列 A={1,2,5,3,4,7};
流程:
dp[i]初值都為1;
1) dp[1]=1;
2)dp[2]=1,A[2]>A[1] dp[2]=max{dp[2], dp[1]+1}=2;
3)dp[3]=1,A[3]>A[3] dp[3]=max{dp[3], dp[1]+1}=2;A[3]>A[2] dp[3]=max{dp[3], dp[2]+1}=3;
4)同上;
5)最後的dp[n]即為最長的序列;
程式碼如下:
#include <iostream>
#include <algorithm>
#define N 100000
using namespace std;
int a[N];
int dp[N];
int main()
{
int n;
while(cin>>n)
{
for(int i=0;i<n;i++)
{
cin>>a[i];
dp[i]=1;
}
for(int i=0;i<n;i++)
{
for(int j=i-1;j>=0;j--)
{
if(a[j]<a[i])
{
dp[i]=max(dp[i],dp[j]+1);
}
}
}
sort(dp,dp+n);
cout<<dp[n-1]<<endl;
}
return 0;
}
方法二:時間複雜度(O(n*logn))
設A[t]=表示序列的第t個元素,f[t]表示長度為t的序列中最後一個數最小的那個數;
因此我們可以知道f[]陣列有一個特殊的性質
f[i]<f[i+1]<f[i+2].......
假設 A[1..9] = 2 1 5 3 6 4 8 9 7,可以看出來它的LIS長度為5。
初始化 len=1;F[1]=A[1]=2;
1)A[2]=1小於F[1] 因此更新F[1]=A[2]=1;len=1;
2)A[3]=3大於F[1]因此F[++len]=A[3];
。。。。。然後
。。。。。繼續
。。。。。更新的結尾
我們模擬這個過程可以發現 更新的時候總是在F找到小於更新值的最大值的位置,因此我們可以用二分進行搜尋
例題:HDU1025 Constructing Roads In JGShining's Kingdom
http://acm.hdu.edu.cn/showproblem.php?pid=1025
程式碼如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 500001;
int p[maxn],f[maxn];//f[i]表示長度為i的序列中最後一個數最小的那個數
int binary_search(int a,int l,int r){//在f[]中找到小於等於a的最大的數的序號
while(l<=r){
int mid=(l+r)>>1;
if(a==f[mid]) return mid;
if(a>f[mid]) l=mid+1;
else r=mid-1;
}
return l;
}
int main()
{
int n,cnt=1;;
while(~scanf("%d",&n)){
int pp,rr;
for(int i=0;i<n;i++){
scanf("%d%d",&pp,&rr);
p[pp]=rr;
}
f[1]=p[1];
int len=1;
for(int i=2;i<=n;i++){
int pos=binary_search(p[i],1,len);
f[pos]=p[i];
if(pos>len)
len++;
}
printf("Case %d:\n",cnt++);
if(len==1)
puts("My king, at most 1 road can be built.");
else
printf("My king, at most %d roads can be built.\n",len);
printf("\n");
}
return 0;
}
相關文章
- 動態規劃7:最長上升子序列LIS動態規劃
- 最長上升子序列LIS 詳解+變形+擴充
- 最長上升子序列
- Codeforces Round #323 (Div. 2) D LIS 最長上升子序列
- 【部分轉載】:【lower_bound、upperbound講解、二分查詢、最長上升子序列(LIS)、最長下降子序列模版】
- DP筆記最長上升子序列(LIS)以及零件分組問題筆記
- 線性dp:最長上升子序列
- NlogN 求最長不下降子序列(LIS)
- 動態規劃:最長上升子序列動態規劃
- 最長上升子序列動態規劃動態規劃
- 動態規劃-最長上升子序列模型動態規劃模型
- 線性dp--最長上升子序列變形
- 動態規劃求解最長上升子序列問題動態規劃
- [線性dp] 合唱隊形(最長上升子序列模型)模型
- 演算法題:最長公共子序列演算法
- LCS 演算法:Javascript 最長公共子序列演算法JavaScript
- 最長公共子序列
- LeetCode 1626. 無矛盾的最佳球隊---【動態規劃】最長上升子序列變換版-->最大上升子序列和LeetCode動態規劃
- 字串篇(python)—兩個字串的最長公共子序列字串Python
- ZOJ 2319 最長上升子序列並輸出組成該序列的元素編號
- 演算法-兩最長迴文子串演算法
- 微軟演算法面試題:如何找最長的增長子序列微軟演算法面試題
- 最長公共子序列(JAVA)Java
- LeetCode 300. 最長上升子序列(Python、動態規劃、貪心演算法)LeetCodePython動態規劃演算法
- 【LeetCode動態規劃#14】子序列系列題(最長遞增子序列、最長連續遞增序列、最長重複子陣列、最長公共子序列)LeetCode動態規劃陣列
- [譯] Swift 演算法學院 - 最長公共子序列演算法Swift演算法
- Leetcode 300 最長遞增子序列(LIS板題)LeetCode
- 北京大學郭煒-最長上升子序列 動態規劃講解動態規劃
- bzoj3173: [Tjoi2013]最長上升子序列(樹狀陣列)陣列
- java 實現 最長公共子序列Java
- 最長公共子序列求方案數
- 線性dp:最長公共子序列
- 經典演算法題每日演練——最長公共子序列演算法
- 最長公共子序列的程式碼實現
- [演算法筆記]動態規劃之最長公共子串和最長公共子序列演算法筆記動態規劃
- 兩個字串的最長公共子串字串
- 動態規劃-最長公共子序列動態規劃
- 動態規劃——最長公共子序列動態規劃