序列dp问题

1.最大子序列和

题目链接:This is the link

题目代码:

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include <iomanip>
#include<list>
#include<map>
#include<queue>
#include<sstream>
#include<stack>
#include<string>
#include<set>
#include<vector>
using namespace std;
#define PI acos(-1.0)
#define EPS 1e-8
#define MOD 1e9+7
#define LL long long
#define ULL unsigned long long     //1844674407370955161
#define INT_INF 0x7f7f7f7f      //2139062143
#define LL_INF 0x7f7f7f7f7f7f7f7f //9187201950435737471
const int dr[]={0, 0, -1, 1, -1, -1, 1, 1};
const int dc[]={-1, 1, 0, 0, -1, 1, -1, 1};
// ios::sync_with_stdio(false);
// 那么cin, 就不能跟C的 scanf,sscanf, getchar, fgets之类的一起使用了。
#define MAX 100000
int num[MAX+5];
int dp[MAX+5];
int main()
{
    int T;
    scanf("%d",&T);
    for(int k=1; k<=T; k++)
    {
        int n,begin,end;
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
            scanf("%d",&num[i]);
        int maxn=-INT_INF;//必须小于-1001,注意
        for(int i=1; i<=n; i++)
        {
            dp[i]=max(num[i],dp[i-1]+num[i]);
            if(maxn<dp[i])
            {
                maxn=dp[i];   //更新最大值
                end=i;       //记录最后数的位置
            }
        }
        int sum=maxn;
        for(int i=end; i>0; i--)
        {
            sum-=num[i];
            if(!sum)
                begin=i;//最长的子序列,加break可以最短子序列,注意
        }
        printf("Case %d:\n%d %d %d\n",k,maxn,begin,end);
        if(k<T)//注意,输出格式
            printf("\n");
    }
    return 0;
}

2.最长上升子序列(Longest Increasing Subsequence,LIS)

题目链接:This is the link

题目代码:(n*n的时间复杂度)

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include <iomanip>
#include<list>
#include<map>
#include<queue>
#include<sstream>
#include<stack>
#include<string>
#include<set>
#include<vector>
using namespace std;
#define PI acos(-1.0)
#define EPS 1e-8
#define MOD 1e9+7
#define LL long long
#define ULL unsigned long long     //1844674407370955161
#define INT_INF 0x7f7f7f7f      //2139062143
#define LL_INF 0x7f7f7f7f7f7f7f7f //9187201950435737471
const int dr[]={0, 0, -1, 1, -1, -1, 1, 1};
const int dc[]={-1, 1, 0, 0, -1, 1, -1, 1};
// ios::sync_with_stdio(false);
// 那么cin, 就不能跟C的 scanf,sscanf, getchar, fgets之类的一起使用了。
int a[1005];
int dp[10005];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;++i)
        scanf("%d",a+i);
    dp[0]=1;//第一个元素的长度为1
    int maxn=1;
    for(int i=1;i<n;++i)
    {
        dp[i]=1;//初始化为1
        for(int j=0;j<i;++j)
        {
            if(a[i]>a[j]&&dp[j]+1>dp[i])//当前元素的大小大于前面的,并且长度小小于前面的
                dp[i]=dp[j]+1;//更新长度
        }
        maxn=max(maxn,dp[i]);
    }
    printf("%d\n",maxn);
    return 0;
}

二分优化(nlongn)

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include <iomanip>
#include<list>
#include<map>
#include<queue>
#include<sstream>
#include<stack>
#include<string>
#include<set>
#include<vector>
using namespace std;
#define PI acos(-1.0)
#define EPS 1e-8
#define MOD 1e9+7
#define LL long long
#define ULL unsigned long long     //1844674407370955161
#define INT_INF 0x7f7f7f7f      //2139062143
#define LL_INF 0x7f7f7f7f7f7f7f7f //9187201950435737471
const int dr[]={0, 0, -1, 1, -1, -1, 1, 1};
const int dc[]={-1, 1, 0, 0, -1, 1, -1, 1};
// ios::sync_with_stdio(false);
// 那么cin, 就不能跟C的 scanf,sscanf, getchar, fgets之类的一起使用了。
int a[1005];
int dp[1005];
int find(int m,int x)
{
    int l=1,r=m;
    int mid;
    while(l<r)
    {
        mid=(l+r)>>1;
        if(x>dp[mid])
            l=mid+1;
        else
            r=mid;
    }
    return l;
}
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;++i)
        cin>>a[i];
    int tot=1;
    dp[1]=a[1];
    for(int i=2;i<=n;++i)
    {
        if(a[i]>=dp[tot])
            dp[++tot]=a[i];
        else
            dp[find(tot,a[i])]=a[i];
    }
    cout<<tot<<endl;
    return 0;
}

3.最长公共子序列(LCS)

// luogu-judger-enable-o2
#include<iostream>
#include<algorithm>
using namespace std;
int s1[100005],s2[100005];
int dp[10005][10005];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;++i)
      cin>>s1[i];
    for(int i=1;i<=n;++i)
      cin>>s2[i];
    for(int i=1;i<=n;++i)
    {
        for(int j=1;j<=n;++j)
        {
            if(s1[i]==s2[j])
                dp[i][j]=dp[i-1][j-1]+1;
            else
                dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
        }
    }
    cout<<dp[n][n];
    return 0;
}

4.最长上升公共子序列(LCIS)

hdu1423  This is the link

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<map>
using namespace std;
typedef long long lld;
const int oo=0x3f3f3f3f;
const lld OO=1LL<<61;
const lld MOD=1000000007;
#define eps 1e-6
#define maxn 505
int dp[maxn][maxn];
int path[maxn][maxn];
int a[maxn],b[maxn];
int n,m;
/*本题不需要输出序列
void dfs(int x)//输出序列
{
    if(path[n][x]==-1)
    {
        printf("%d",b[x]);
        return ;
    }
    dfs(path[n][x]);
    printf(" %d",b[x]);
}
*/
int main()
{
    int t;
    scanf("%d",&t);
    for(int k=1;k<=t;++k)
    {
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
            scanf("%d",&a[i]);
        scanf("%d",&m);
        for(int i=1; i<=m; i++)
            scanf("%d",&b[i]);
        memset(dp,0,sizeof dp);
        memset(path,-1,sizeof path);
        for(int i=1; i<=n; i++)//实现过程
        {
            int pos=-1,Max=0;
            for(int j=1; j<=m; j++)
            {
                dp[i][j]=dp[i-1][j];
                path[i][j]=path[i-1][j];
                if(a[i]==b[j]&&dp[i][j]<Max+1)
                {
                    dp[i][j]=Max+1;
                    path[i][j]=pos;
                }
                if(a[i]>b[j]&&dp[i-1][j]>Max)
                {
                    Max=dp[i-1][j];
                    pos=j;
                }
            }
        }
        int ans=1;
        for(int i=1; i<=m; i++)
            if(dp[n][ans]<dp[n][i])
                ans=i;
        printf("%d\n",dp[n][ans]);//格式要求很严
        if(k<t)
            puts("");//输出换行
    /*本题不需要输出序列
        if(dp[n][ans])
            dfs(ans);
        puts("");//换行
        */
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sdau_fangshifeng/article/details/81780458
今日推荐