动态规划--最长递增子序列(LIS)-最长公共子序列(LCS)

LIS
最长递增子序列,朴素的是o(n^2)算法,二分下可以写成o(nlgn):维护一个当前最优的递增序列——找到恰好大于它更新
LCS

最长公共子序列,通常o(n^2)的算法

********************************************************************************************************************

LIS:
题目大意:给定序列个数n及n个数,求该序列的最大连续子序列的和,要求输出最大连续子序列的和以及子序列的首位位置

解题思路:经典DP,可以定义 dp[i]表示以a[i]为结尾的子序列的和的最大值,因而最大连续子序列及为dp数组中的最大值。
状态转移方程:dp[1] = a[1]; //以a[1]为结尾的子序列只有a[1];
                        i >= 2时, dp[i] = max( dp[i-1]+a[i],  a[i] );  
/* HDU 1003 Max Sum --- 经典DP */  
#include <cstdio>#include <cstring>  
int dp[100005];  
int main()   
{  
    int t, n;      
    int kase = 0;      
    int fst, lst, maxSum; //记录首位位置以及最大和      
    int start; //start是用于记录中间变化的起点的      
    scanf("%d", &t);      
    while (t--)  
    {  
        scanf("%d", &n);  
        for (int i = 0; i < n; ++i)  
        {  
            scanf("%d", dp + i);  
        }  
        start = fst = lst = 0;  
        maxSum = dp[0];  
        for (int i = 1; i < n; ++i)  
        {            //dp[i] = MAX(dp[i - 1] + dp[i], dp[i]);             
            if (dp[i - 1] >= 0)  
            {  
                dp[i] = dp[i - 1] + dp[i];  
            }  
            else  
            {  
                start = i; //抛弃dp[i-1],则起点发生变化            }  
  
                if (dp[i] > maxSum)  
                {                //若当前求得的子序列和最大,进行更新                 
                    maxSum = dp[i];  
                    fst = start;  
                    lst = i;  
                }  
            }  
            if (kase)  
            {  
                printf("\n");  
            }  
            printf("Case %d:\n", ++kase);  
            printf("%d %d %d\n", maxSum, fst + 1, lst + 1);  
        }  
    }  
    return 0;  
}
例:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值