首页 > 代码库 > 各种子序列问题

各种子序列问题

最长严格上升子序列

LIS问题,动归时间复杂度o(n2),可以用单调队列优化到o(nlogn)

http://blog.csdn.net/dangwenliang/article/details/5728363

#include<iostream>#include<cstdio>#include<algorithm>using namespace std;int n,dp[5005],orz[5005],ans = 0;int main(){    cin>>n;    for(int i = 1;i <= n;i++) scanf("%d",&orz[i]);    for(int i = 1;i <= n;i++){        dp[i] = 1;        for(int j = 1;j < i;j++){            if(orz[i] > orz[j])dp[i] = max(dp[i],dp[j]+1);            ans = max(ans,dp[i]);        }    }    cout<<ans;    return 0;}
#include <iostream>using namespace std;int find(int *a,int len,int n)//修改后的二分查找,若返回值为x,则a[x]>=n{    int left=0,right=len,mid=(left+right)/2;    while(left<=right)    {       if(n>a[mid]) left=mid+1;       else if(n<a[mid]) right=mid-1;       else return mid;       mid=(left+right)/2;    }    return left;}     int main(void){    int n,a[100],c[100],i,j,len;//新开一变量len,用来储存每次循环结束后c中已经求出值的元素的最大下标    while(cin>>n)    {        for(i=0;i<n;i++)            cin>>a[i];        b[0]=1;        c[0]=-1;        c[1]=a[0];        len=1;//此时只有c[1]求出来,最长递增子序列的长度为1.        for(i=1;i<n;i++)        {            j=find(c,len,a[i]);            c[j]=a[i];            if(j>len)//要更新len,另外补充一点:由二分查找可知j只可能比len大1                len=j;//更新len        }        cout<<len<<endl;    }    return 0;}

合唱队形

#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<algorithm>using namespace std;const int maxn = 200;int dp[maxn],dps[maxn],value[maxn],n;int main(){    cin>>n;    for(int i =1;i <= n;i++) cin>>value[i];    dp[1] = dps[n] = 1;    for(int i = 2;i <= n;i++){        for(int j = 1;j < i;j++){            if(dp[j] > dp[i] && value[i] > value[j]) dp[i] = dp[j];        }        dp[i]++;            }    for(int i = n-1;i >= 1;i--){        for(int j = n;j > i;j--){            if(dps[j] > dps[i] && value[i] > value[j]) dps[i] = dps[j];        }        dps[i]++;            }    int ans = 0;    for(int i = 1;i <= n;i++) ans = max(ans,dp[i] + dps[i] - 1);    cout<<n - ans;    return 0;}

 

各种子序列问题