简单DP:子序列问题

最大连续子序列

给定K个整数的序列{ N1, N2, …, NK },其任意连续子序列可表示为{ Ni, Ni+1, …,
Nj },其中 1 <= i <= j <= K。最大连续子序列是所有连续子序列中元素和最大的一个,
例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{ 11, -4, 13 },最大和
为20。
在今年的数据结构考卷中,要求编写程序得到最大和,现在增加一个要求,即还需要输出该
子序列的第一个和最后一个元素。
Input
测试输入包含若干测试用例,每个测试用例占2行,第1行给出正整数K( < 10000 ),第2行给出K个整数,中间用空格分隔。当K为0时,输入结束,该用例不被处理。
Output
对每个测试用例,在1行里输出最大和、最大连续子序列的第一个和最后一个元
素,中间用空格分隔。如果最大连续子序列不唯一,则输出序号i和j最小的那个(如输入样例的第2、3组)。若所有K个元素都是负数,则定义其最大和为0,输出整个序列的首尾元素。

#include <iostream>
using namespace std;
int main()
{
    int a[10006];
    int n;
    while((cin>>n)&&(n!=0))
    {
      int be=0,en=0,maxn=0;
      int flag=0;
      for(int i=1;i<=n;i++)
      {
          cin>>a[i];
          if(a[i]>=0)
            flag=1;
      }
      if(flag==0)
      {cout<<'0'<<" "<<a[1]<<" "<<a[n]<<endl;
      continue;}
      int tem=0,p=a[1];
      for(int i=1;i<=n;i++)
      {
           if(tem<0)
           {
               tem=0;
               p=a[i];
           }
           tem+=a[i];
           if(tem>maxn)
           {
               maxn=tem;
               en=a[i];
               be=p;
           }
      }
      cout<<maxn<<" "<<be<<" "<<en<<endl;
    }
    return 0;
}

典型的最大连续子序列问题,解题思路:对当前元素进行判断,有两种情况,之前的最大子序列加上新增元素或者开新的最大子序列,如果之前子序列和是负的,则这个加上这个元素一定会小于元素本来的大小,所以重新开始找最大子序列。

Given a sequence a[1],a[2],a[3]…a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14.
Input
The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line starts with a number N(1<=N<=100000), then N integers followed(all the integers are between -1000 and 1000).
Output
For each test case, you should output two lines. The first line is “Case #:”, # means the number of the test case. The second line contains three integers, the Max Sum in the sequence, the start position of the sub-sequence, the end position of the sub-sequence. If there are more than one result, output the first one. Output a blank line between two cases.

#include <iostream>
using namespace std;
int main()
{
    int a[100006];
    int t;
    cin>>t;
    for(int z=1;z<=t;z++)
    {
      int be=0,en=0,maxn=-100008;
      int flag=0;
      int n;
      cin>>n;
      int small=0,s;
      for(int i=1;i<=n;i++)
      {
          cin>>a[i];
      }
      int tem=0,p=1;
      for(int i=1;i<=n;i++)
      {
           tem+=a[i];
           if(tem>maxn)
           {
               maxn=tem;
               en=i;
               be=p;
           }
           if(tem<0)
           {
               tem=0;
               p=i+1;
           }
      }
      cout<<"Case "<<z<<":"<<endl;
      cout<<maxn<<" "<<be<<" "<<en<<endl;
      if(z!=t)
        cout<<endl;
    }
    return 0;
}

变式

最小连续子序列

Dynamic Programming, short for DP, is the favorite of iSea. It is a method for solving complex problems by breaking them down into simpler sub-problems. It is applicable to problems exhibiting the properties of overlapping sub-problems which are only slightly smaller and optimal substructure.
Ok, here is the problem. Given an array with N integers, find a continuous subsequence whose sum’s absolute value is the smallest. Very typical DP problem, right?

#include <iostream>
#include <cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int a[1006];
int main()
{
    int t;
    cin>>t;
    for(int z=1;z<=t;z++)
    {
        int n,maxs=1e5+6;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        for(int i=1;i<=n;i++)
        {
        int sum=0 ;
          for(int j=i;j<=n;j++)
          {
            sum+=a[j];
            maxs=min(abs(sum),maxs);
          }
        }
        cout<<"Case "<<z<<": "<<maxs<<endl;
    }
    return 0;
}

另一种方法,运算时间大于第一种,遍历每一个子序列,在较大测试数据时容易超时

最长公共子序列

A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = <x1, x2, …, xm> another sequence Z = <z1, z2, …, zk> is a subsequence of X if there exists a strictly increasing sequence <i1, i2, …, ik> of indices of X such that for all j = 1,2,…,k, xij = zj. For example, Z = <a, b, f, c> is a subsequence of X = <a, b, c, f, b, c> with index sequence <1, 2, 4, 6>. Given two sequences X and Y the problem is to find the length of the maximum-length common subsequence of X and Y.
The program input is from a text file. Each data set in the file contains two strings representing the given sequences. The sequences are separated by any number of white spaces. The input data are correct. For each set of data the program prints on the standard output the length of the maximum-length common subsequence from the beginning of a separate line.

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
int dp[10006][10006];
int main()
{
    string t,s;
    int l1,l2;
    while(cin>>t>>s)
    {
        l1=t.length();
        l2=s.length();
        for(int i=0;i<=l1;i++)
        {
            for(int j=1;j<=l2;j++)
            {
                if((i==0)||(j==0))
                {
                    dp[i][j]=0;
                    continue;
                }
                if(t[i-1]==s[j-1])
                    dp[i][j]=dp[i-1][j-1]+1;
                else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
            }
        }
        cout<<dp[l1][l2]<<endl;
    }
    return 0;
}

头文件问题,可能是.length()函数的问题,前几次显示compile error,遍历所有情况,先按照第一个数组,

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值