动态规划经典模型整理

最长上升子序列:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int n,ans=1;
int sequence[10000],f[10000];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	scanf("%d",&sequence[i]);
	/*f[1] = 1;
	for(int i=2;i<=n;++i)
	{
		f[i]=1;//到i为止的最长上升子序列长度
		for(int j=1;j<i;++j)
		if(sequence[j]<sequence[i])//“<=”不下降子序列
		f[i]=max(f[i],f[j]+1);
	}
	printf("%d",f[n]);*/
	f[1]=sequence[1];
	for(int i=2;i<=n;i++)
	{
		if(sequence[i]>f[ans])
		f[++ans]=sequence[i];
		else
		{
			/*int l=1,r=ans;
			while(l<r)
			{
				int mid=(l+r+1)/2;
				if (f[mid]<=sequence[i])
				l=mid;
				else
				r=mid-1;
			}
			int j=l;*/
			int j=upper_bound(f+1,f+ans+1,sequence[i])-f;
			f[j]=sequence[i];
		}
	}
	printf("%d",ans);
	return 0;
}

最长公共子序列:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int f[5000][5000];
char a[10000],b[10000];
int main()
{
	while(~scanf("%s%s",a+1,b+1))
	{
		int len1=strlen(a+1);
		int len2=strlen(b+1);
		f[0][0]=0;//a串匹配到第i位,b串第j位的最长公共子序列长度 
		for(int i=1;i<=len1;i++)
		{
			for(int j=1;j<=len2;j++)
			{
				f[i][j]=max(f[i-1][j],f[i][j-1]);
				if(a[i]==b[j])//注意不要写成a[i]==b[i]
				f[i][j]=max(f[i][j],f[i-1][j-1]+1);
			}
		}
		printf("%d\n",f[len1][len2]);
	}
	return 0;
}

最长公共子串:

Codevs 1425 最长公共子串

取前两个字符串求最长公共子串。
再用公共子串和下一个字符串找公共子串,以此类推。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int mod = 100000000;
char a[1000010],b[1000010];
int n,ans,lan,lbn,pos;
int dp[3010][3010];
int main()
{
	scanf("%d",&n);
	scanf("%s",a+1);
	lan=strlen(a+1);
	for(int i=2;i<=n;i++)
	{
		ans=0;
		scanf("%s",b+1);
		lbn=strlen(b+1);
		for(int i=1;i<=lan;i++)
		{
			for(int j=1;j<=lbn;j++)
			{
				if(a[i]==b[j])	
				{
					dp[i][j]=dp[i-1][j-1]+1;
					if(dp[i][j]>ans)
					{
						ans=dp[i][j];
						pos=j;
					}
				}
			}
		}
		memset(a,0,sizeof(a));
		int tmp=ans;
		for(int i=1;i<=ans;i++)
		a[i]=b[pos-tmp+1],tmp--;
		lan=strlen(a+1);
	}
	for(int i=1;i<=ans;i++)
	printf("%c",a[i]);
	return 0;
}

最长公共上升子序列:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int n,m,maxn,ans;
int a[100000],b[100000],f[5000][5000];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	scanf("%d",&a[i]);
	//scanf("%d",&m);
	m=n;
	for(int i=1;i<=m;i++)
	scanf("%d",&b[i]);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(a[i]!=b[j])
			f[i][j]=f[i-1][j];
			if(a[i]==b[j])
			{
				maxn=0;
				for(int k=1;k<=j-1;k++)
				{
					if(b[j]>b[k])
					maxn=max(maxn,f[i-1][k]);
				}
				f[i][j]=maxn+1;
			}
		}
	}
	for(int i=1;i<=m;i++)
	ans=max(ans,f[n][i]);
	printf("%d",ans);
	return 0;
}

最大子段和:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n,ans;
int num[1000010],dp[1000010];//dp[i]以i结尾的最大子段和 
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	scanf("%d",&num[i]);
	for(int i=1;i<=n;i++)
	{
		if(dp[i-1]>0)
		dp[i]=dp[i-1]+num[i];//这样若dp[i]为正数,正确,若为负数,一定不会作为答案不影响正确性 
		else dp[i]=num[i];//前面的负数必然不能使当前值更大 
		if(dp[i]>ans)
		ans=dp[i];
	}
	printf("%d",ans);
	return 0;
}
    原文作者:动态规划
    原文地址: https://blog.csdn.net/qq_36693533/article/details/78484891
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞