LIS(最长上升子序列长度)

https://vijos.org/p/1028

#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
#define logic(a,b) (strstr((a),(b)) == (a))
char s[2001][75];
int main(){
    int n;
    cin>>n;
    for (int i = 0; i < n; ++i)cin>>s[i];
    int f[2001] = {0};
    int ans = 1;
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < i; ++j)
            if (logic(s[i],s[j]))
                f[i] = max(f[i],f[j]+1);
        ans = max(ans,f[i]);
    }
    cout << ans+1 << endl;
    return 0;
}

http://acm.nyist.net/JudgeOnline/problem.php?pid=79

#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
const int N=25;
int dp[N],w[N];
int main(){
    int n,i,j,ans,text;
    cin>>text;
    while(text--)
    {
        cin>>n;
        memset(dp,0,sizeof(dp));
        for (i=0;i<n;i++) cin>>w[i];
        ans=0;
        for (i=0;i<n;i++)
        {
            for (j=0;j<i;j++)
                if(w[i]<w[j])   dp[i]=max(dp[i],dp[j]+1);//< 代表递减    >代表递增
            ans=max(ans,dp[i]);
        }
        cout<<ans+1<< endl;
    }
    return 0;
}

https://vijos.org/p/1098

#include<stdio.h>
int s[101],f[101],g[101];
int n;
void max(int& a,int b){ if(a<b)a=b; }
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;++i){
        scanf("%d",s+i);
        f[i]=g[i]=1;
    }
    for(int i=1;i<n;++i)
        for(int j=0;j<i;++j)
            if(s[i]>s[j]) max(f[i],f[j]+1);
    for(int i=n-2;~i;--i)
        for(int j=n-1;j>i;--j)
            if(s[i]>s[j]) max(g[i],g[j]+1);
    int ans=0;
    for(int i=0;i<n;++i) max(ans,f[i]+g[i]);
    printf("%d",n-ans+1);
}

http://poj.org/problem?id=3903

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int a[100005],dp[100005],n;
int bin(int size,int k)
{
    int l=1,r=size;
    while(l<=r)
    {
        int mid =(l+r)/2;
        if(k>dp[mid])    l = mid+1;
        else            r = mid-1;
    }
    return l;
}
int lis()
{
    int i,j,cnt=0,k;
    for(i=1;i<=n; i++)
    {
        if(cnt==0||a[i]>dp[cnt])  dp[++cnt] = a[i];
        else
        {
           k = bin(cnt,a[i]);
           dp[k]=a[i];
        }
    }
    return cnt;
}
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++)  scanf("%d",&a[i]);
        printf("%d\n",lis());
    }
    return 0;
}

https://www.bnuoj.com/v3/problem_show.php?pid=49098

分析这个问题会自然地想到最长递增子序列(Longest Increasing Subsequence),因为不需要修改的人组成的序列肯定是这样一个序列。

但是经过分析,我们并不能通过直接求出原序列的LIS长度用总长度减去它来得到答案,这是因为原序列的LIS可能会含有这类情况:

1,1,2,3 虽然最长的LIS长度为3,但是我们不能只把一个1改为2,因为它遇到了“相等”这一情况,修改后身高不是严格递增的。

这会让我们思考如何求一个与原序列有关,其LIS的情况哪怕是遇到“相等”也满足修改后原序列严格递增的。

一个容易想到的情况是,把序列中的所有数减去一个单调递增的序列得到新序列,这个新序列中,即便修改后遇到相等,加上原来的递增数列,原序列依旧严格递增

那么,我们应该减去什么序列呢?分析原题,我们不难发现完美的身高序列中每个人的身高都要大于其所占位置(从0开始计数)的序号,

判断条件即减去从1开始的正整数列,小于等于零的消去,人数暂记为ans,因为这些一定会要修改,把结果大于零的输入一个新数列,这个新数列的LIS值就是不需要修改的那些值,另一类人数为tot,现在需要求的是它的每个元素减去下标后的最长上升子序列(LIS)长度dnum,利用动态规划就能实现

最后的答案是ans=ans+tot-dnum

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
const int maxn = 1e5+10;
int a[maxn];
int b[maxn];
int dp[maxn];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        int num=0,ans=0,tot=0;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            a[i]-=i;
            if(a[i]<1){ ans++; }
            else{ b[tot++]=a[i]; }
        }
        int dnum=0;
        for(int i=0;i<tot;i++)
        {
            int pos = upper_bound(dp,dp+dnum,b[i])-dp;
            if(pos==dnum)
                dp[dnum++]=b[i];
            else dp[pos]=b[i];
        }
            ans=ans+tot-dnum;
            printf("%d\n",ans);
        }
    return 0;
}



你可能感兴趣的:(ACM)