线性dp入门(求最大和+最长上升子序列+最长公共子序列)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_41117236/article/details/82011379

【题目】

The Triangle

【题解】

题意:输出从下往上走的最大和。

思路:最后一行dp[i][j]=a[i][j]

状态转移方程:dp[i][j]=a[i][j]+max(dp[i+1][j],dp[i+1][j+1])

【代码】

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <stack>
#include <queue>
#include <algorithm>
#include <iostream>
#define mem(a) memset(a,0,sizeof(a))
#define go(i,a,b) for(int i=a;i<=b;i++)
#define og(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
main()
{
    int n,a[105][105],dp[105][105];
    cin>>n;
    go(i,1,n)
    {
        go(j,1,i) cin>>a[i][j];
    }
    og(i,n,1)
    {
        go(j,1,i)
        {
            if(i==n) dp[i][j]=a[i][j];
            else dp[i][j]=a[i][j]+max(dp[i+1][j],dp[i+1][j+1]);
        }
    }
    cout<<dp[1][1]<<endl;
}

【题目】

开宝箱

【题解】

题意:输出从左上角到右下角所能得到的最大和。

思路:初始位置dp[i][j]=a[i][j],dp[][]要初始化为最小值。

状态转移方程:dp[i][j]=a[i][j]+max(dp[i-1][j],dp[i][j-1])

【代码】

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <stack>
#include <queue>
#include <algorithm>
#include <iostream>
#define mem(a) memset(a,0,sizeof(a))
#define go(i,a,b) for(int i=a;i<=b;i++)
#define og(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
main()
{
    int n,m,a[105][105],dp[105][105];
    int t; scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        go(i,1,n)
        {
            go(j,1,m) scanf("%d",&a[i][j]);
        }
        go(i,0,n)
        {
            go(j,0,m) dp[i][j]=-inf;
        }
        go(i,1,n)
        {
            go(j,1,m)
            {
                if(i==1&&j==1) dp[i][j]=a[i][j];
                else dp[i][j]=a[i][j]+max(dp[i-1][j],dp[i][j-1]);
            }
        }
        printf("%d\n",dp[n][m]);
    }
}

【题目】

最长上升子序列

【题解】

思路:每次求以第i个数为终点的最长上升子序列的长度,然后更新答案。

状态转移方程:dp[i]=max(dp[i],dp[j]+1)

【代码】

//朴素dp O(n^2)
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <stack>
#include <queue>
#include <algorithm>
#include <iostream>
#define mem(a) memset(a,0,sizeof(a))
#define go(i,a,b) for(int i=a;i<=b;i++)
#define og(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
main()
{
    int n,a[1005],dp[1005];
    cin>>n; int ans=0;
    go(i,1,n) cin>>a[i],dp[i]=1;
    go(i,1,n)
    {
        go(j,1,i) if(a[j]<a[i]) dp[i]=max(dp[i],dp[j]+1);
        ans=max(ans,dp[i]);
    }
    cout<<ans<<endl;
}

//贪心+二分 O(nlogn)
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <stack>
#include <queue>
#include <algorithm>
#include <iostream>
#define mem(a) memset(a,0,sizeof(a))
#define go(i,a,b) for(int i=a;i<=b;i++)
#define og(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
main()
{
    int n,a[1005],dp[1005];
    cin>>n;
    go(i,1,n) cin>>a[i];
    int l=1;dp[1]=a[1];
    go(i,1,n)
    {
        if(a[i]>dp[l]) dp[++l]=a[i];
        else
        {
            int t=upper_bound(dp+1,dp+l+1,a[i])-dp;
            dp[t]=a[i];
        }
    }
    cout<<l<<endl;
}

【题目】

最长公共子序列

【代码】

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <stack>
#include <queue>
#include <algorithm>
#include <iostream>
#define mem(a) memset(a,0,sizeof(a))
#define go(i,a,b) for(int i=a;i<=b;i++)
#define og(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
int dp[1005][1005];
main()
{
    string a,b;
    while(cin>>a>>b)
    {
        mem(dp);
        int l1=a.size(),l2=b.size();
        go(i,1,l1)
        {
            go(j,1,l2)
            {
                //状态转移方程
                if(a[i-1]==b[j-1]) dp[i][j]=dp[i-1][j-1]+1;
                else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
            }
        }
        printf("%d\n",dp[l1][l2]);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41117236/article/details/82011379