线性DP 入门

版权声明:https://blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/84572083

1.最长上升子序列LIS问题

// 一个序列中的最长上升子序列(LIS)输出路径 O(n^2)
#include <iostream>
using namespace std;
const int MAXN = 1e3 + 10;
int n, data[MAXN];
int dp[MAXN]; 
int from[MAXN]; 
void output(int x)
{
    if(!x)return;
    output(from[x]);
    cout<<data[x]<<" ";
    //迭代输出 
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)cin>>data[i];

    // DP
    for(int i=1;i<=n;i++)
    {
        dp[i]=1;
        from[i]=0;
        for(int j=1;j<i;j++)
        if(data[j]<data[i] && dp[i]<dp[j]+1)
        {
            dp[i]=dp[j]+1;
            from[i]=j;//逐个记录前驱 
        }
    }

    int ans=dp[1], pos=1;
    for(int i=1;i<=n;i++)
        if(ans<dp[i])
        {
            ans=dp[i];
            pos=i;//由于需要递归输出
    //所以要记录最长上升子序列的最后一
    //个元素,来不断回溯出路径来 
        }
    cout<<ans<<endl;
    output(pos);

    return 0;
}

2.最长公共子序列LCS问题

https://www.luogu.org/problemnew/show/P1439

#include<bits/stdc++.h>
using namespace std;
const int __=100010;
const int INF=0x7fffffff;
inline int read()
{
	int f=1,num=0;
	char ch=getchar();
	while (ch<'0'||ch>'9') { if (ch=='-') f=-1; ch=getchar(); }
	while (ch>='0'&&ch<='9') num=(num<<1)+(num<<3)+ch-'0', ch=getchar();
	return num*f;
}
int a[__],b[__];
int belong[__];
int f[__],len;
int main()
{
	int n=read();
	for (int i=1;i<=n;++i)
	{
		a[i]=read();
		belong[a[i]]=i;//离散化 
	}
	for (int i=1;i<=n;++i)
	{
		b[i]=read();
		f[i]=INF;
	}
	f[0]=0;
	for (int i=1;i<=n;++i)
	{
		int l=0,r=len,mid;
		if (belong[b[i]]>f[len])
			f[++len]=belong[b[i]];
		else
		{
			while (l<r)
			{
				mid=(l+r)>>1;
				if (f[mid]>belong[b[i]])
					r=mid;
				else
					l=mid+1;
			}
			f[l]=min(belong[b[i]],f[l]);
		}
	}
	printf("%d\n",len);
	return 0;
}

3.数字三角形

#include<bits/stdc++.h>
using namespace std;
const int maxnum=1500;
int a[maxnum][maxnum],f[maxnum][maxnum];
inline int read()
{
	int f=1,num=0;
	char ch=getchar();
	while (ch<'0'||ch>'9') { if (ch=='-') f=-1; ch=getchar(); }
	while (ch>='0'&&ch<='9') { num=(num<<1)+(num<<3)+ch-'0'; ch=getchar(); }
	return num*f;
}
int main()
{
	int n=read();
	for (int i=1;i<=n;i++)
		for (int j=1;j<=i;j++)
			a[i][j]=read();
	for (int i=1;i<=n;i++)
		f[i][n]=a[i][n];//先把f(i+1)一组计算好。 
	for (int i=n;i>0;i--)
		for (int j=1;j<=i;j++)
			f[i][j]=max(f[i+1][j],f[i+1][j+1])+a[i][j];
	cout<<f[1][1];
	return 0;
}

猜你喜欢

转载自blog.csdn.net/huashuimu2003/article/details/84572083
今日推荐