经典Dp题目

1. Hdu   Max  sum :

题意:  最大连续和,但要输出这个序列的起始和末尾;

     两种线性时间算法:   1,前缀和       S[j]--S[i-1]:     S[i-1]最小

                                          2,Dp   状态转移方程  :  S[i]=Max(0, S[i-1])+A[i];

 #include<iostream>
#define N 100010
using namespace std;
int a[N],d[N];
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.cpp","r",stdin);
#endif // ONLINE_JUDGE
    int test,n,i,Max,k,f,e;
    cin>>test;
    k=0;
    while(test--)
    {
        cin>>n;
        for(i=1;i<=n;i++)
            cin>>a[i];
        d[0]=0;
        for(int i=1;i<=n;i++)
            d[i]=d[i-1]+a[i];
        Max=-9999;
        int Min=d[0];
        for(int i=1;i<=n;i++)
        {
            if(d[i]-Min>Max)  { Max=d[i]-Min; e=i;}
            if(d[i]<Min)   Min=d[i];
        }
        f=e;
        int t=0;
        for(int i=e;i>0;i--)
        {
            t+=a[i];
            if(t==Max)  f=i;
        }
        printf("Case %d:\n",++k);
        printf("%d %d %d\n",Max,f,e);
        if(test) cout<<endl;
    }
    return 0;
}

2. poj   2533  Longest Ordered Subsequence

最长上升子序列:   状态转移方程: Dp[i]== max(dp[j] ( i<j.A[i]<A[j] )) +1;

const int maxn=1010;
using namespace std;
int  dp[maxn];
int A[maxn];
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.cpp","r",stdin);
#endif // ONLINE_JUDGE
    int n;
    while(scanf("%d",&n)!=EOF)
     {
          for(int i=1;i<=n;i++)
            scanf("%d",&A[i]);
           dp[1]=1;
           int Max=1;
           int m;
         for(int i=2;i<=n;i++)
         {
             m=0;
            for(int j=1;j<i;j++)
            {
                if(A[j]<A[i]&&dp[j]>=m)
                    m=dp[j];
            }
            dp[i]=m+1;
            if(dp[i]>Max)  Max=dp[i];
         }
         printf("%d\n",Max);
     }
    return 0;
}

 nlogn :

#define MP make_pair
#define PB push_back
#define AA first
#define BB second
#define BG begin()
#define ED end()
#define SZ size()

int a[100005];
int main(){
     #ifndef ONLINE_JUDGE
    freopen("in.cpp","r",stdin);
    #endif // ONLINE_JUDGE
    int i,n,j,k,_T;
        while(scanf("%d",&n)==1){
        for(i=1;i<=n;i++)scanf("%d",&a[i]);
        vector<int>L;
        for(i=1;i<=n;i++){
            int id=std::lower_bound(L.OP,L.ED,a[i])-L.OP;
            if(id==L.SZ)L.PB(a[i]);
            else L[id]=a[i];
        }
        printf("%d\n",L.SZ);
        }

    return 0;
}


       uva  10635   Prince and Princess

  用nlogn 解决最长递增子序列。 

  将求最长公共子序列转化为求最长递增子序列

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
const int maxn=65000;
const int inf=1000000000;
int A[maxn];
int B[maxn];
int C[maxn];
int D[maxn];

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.cpp","r",stdin);
#endif // ONLINE_JUDGE
    int t;
    cin>>t;
    int Cas=0;
    while(t--)
    {
        int n,p,q;
        scanf("%d%d%d",&n,&p,&q);
        int x;
        memset(A,0,sizeof(A));
        for(int i=1;i<=p+1;i++)
            {
                scanf("%d",&x);
                A[x]=i;
            }
        int y;
        int s=0;
        for(int i=1;i<=q+1;i++)
            {
                scanf("%d",&y);
                if(A[y])  B[s++]=A[y];
            }
         for(int i=0;i<=s;i++)  C[i]=inf;
         int ans=0,k;
         for(int i=0;i<s;i++)
         {
              k=lower_bound(C+1,C+s,B[i])-C;
             D[i]=k;
             C[k]=B[i];
             ans=max(ans,D[i]);
         }
         printf("Case %d: %d\n",++Cas,ans);
    }
}





3. poj   1458   Longest Common Subsequence

最长公共子序列: 

状态转移: if(str1[i-1]==str2[j-1]) dp[i][j]=dp[i-1][j-1]+1;

              else     dp[i][j]=max(dp[i-1][j],dp[i][j-1]);

const int maxn=305;
string str1,str2 ;
int dp[maxn][maxn];
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.cpp","r",stdin);
#endif // ONLINE_JUDGE

    int h1,h2;
    while(cin>>str1>>str2)
    {
        h1=str1.size();
        h2=str2.size();
        memset(dp,0,sizeof(dp));
        for(int i=1; i<=h1; i++)
        {
            for(int j=1; j<=h2; j++)
            {
                if(str1[i-1]==str2[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[h1][h2]);
        getchar();
    }

    return 0;
}</span>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值