acm DP经典5题

来源:互联网 发布:歌曲伴奏制作软件下载 编辑:程序博客网 时间:2024/06/06 05:29

1.最大连续子序列

给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= K。最大连续子序列是所有连续子序中元素和最大的一个, 例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{ 11, -4, 13 },最大和为20。

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



#include<iostream>#include<cstdio>#include<cstring>#include<ctime>#include<algorithm>#include <map>#include <set>using namespace std;//2015.4.1//最大连续子序列  假设100个数typedef long long LL;int dp[100];int a[100];int n;int main(){    while(true)    {        memset(dp,0,sizeof(dp));        cin>>n;        for(int i=1;i<=n;i++)        {            cin>>a[i];        }        dp[1]=a[1];        for(int i=2;i<=n;i++)        {            dp[i]=max(dp[i-1]+a[i],a[i]);        }        printf("%d\n",dp[n]);    }    return 0;}

2.数塔问题


数塔问题 :要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?


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

#include<iostream>#include<cstdio>#include<cstring>#include<ctime>#include<algorithm>#include <map>#include <set>using namespace std;//2015.4.1//数塔typedef long long LL;int n;int dp[100][100];int a[100][100];int main(){    while(true)    {        cin>>n;        int key=1;        for(int i=1;i<=n;i++)        {            for(int j=1;j<=i;j++)            {                cin>>a[i][j];                if(i==n)                {                    dp[i][j]=a[i][j];                }            }            for(int i=n-1;i>=1;i--)            {                for(int j=1;j<=i;j++)                {                    dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+a[i][j];                }            }        }        cout<<dp[1][1]<<endl;    }    return 0;}

3.背包问题


N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。


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

#include<iostream>#include<cstdio>#include<cstring>#include<ctime>#include<algorithm>#include <map>#include <set>using namespace std;//2015.4.1//背包问题int c[100],w[100];int dp[100][100];//前i个物品中选j重int n,v;int main(){    while(true)    {        memset(dp,0,sizeof(dp));        cin>>n>>v;        for(int i=1;i<=n;i++)        {            cin>>c[i]>>w[i];        }        for(int i=1;i<=n;i++)        {            for(int j=1;j<=v;j++)            {                dp[i][j]=max(dp[i-1][j],dp[i][j-w[i]]+c[i]);            }        }        cout<<dp[n][v]<<endl;    }    return 0;}

4.最长递增子序列

给定一个序列 An a1 ,a2 ,  ... , an ,找出最长的子序列使得对所有 j ,ai aj 

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

#include<iostream>#include<cstdio>#include<cstring>#include<ctime>#include<algorithm>#include <map>#include <set>using namespace std;//2015.4.1//最长递增子序列int f[100];int a[100];int n;int ans;int main(){    while(true)    {        cin>>n;        ans=1;        for(int i=1;i<=n;i++)        {            cin>>a[i];            f[i]=1;        }        for(int i=2;i<=n;i++)        {            for(int j=i-1;j>=1;j--)            {                if(a[i]>a[j]&&f[i]<=f[j])                {                    f[i]=f[j]+1;                    if(f[i]>ans)ans=f[i];                }            }        }        cout<<ans<<endl;    }    return 0;}


5.最长公共子序列

一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。

这个题似乎常用来检测是否一篇文章时抄袭的。

状态转移方程:if(a[i]==b[j])dp[i][j]=dp[i-1][j-1]+1
else if(a[i]!=a[j]) dp[i][j]=dp[i-1][j-1]
      if(i==0||j==0)dp[i][j]=0

#include<iostream>#include<cstdio>#include<cstring>#include<ctime>#include<algorithm>#include <map>#include <set>using namespace std;//2015.4.1//最长公共子序列int dp[100][100];int a[100];int b[100];int n,m;int main(){    while(true)    {        cin>>n>>m;        for(int i=1;i<=n;i++)        {            cin>>a[i];            dp[i][0]=0;        }        for(int j=1;j<=m;j++)        {            cin>>b[j];            dp[0][j]=0;        }        dp[0][0]=0;        for(int i=1;i<=n;i++)        {            for(int j=1;j<=m;j++)            {                if(a[i]==b[j])                {                    dp[i][j]=dp[i-1][j-1]+1;                }                else if(dp[i][j-1]>=dp[i-1][j])                {                    dp[i][j]=dp[i][j-1];                }                else                {                    dp[i][j]=dp[i-1][j];                }            }        }        cout<<dp[n][m]<<endl;    }    return 0;}



0 0