动态规划经典模型整理

来源:互联网 发布:淘宝实拍保护怎么破解 编辑:程序博客网 时间:2024/05/29 17:42

最长上升子序列:

#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;}
原创粉丝点击