zoukankan      html  css  js  c++  java
  • 【动态规划】【子序列模板】

    ACM模板

    【最长上升子序列】

    输出长度

    while(scanf("%s%s",s1+1,s2+1)!=EOF)
        {
            l1 = strlen(s1+1);
            l2 = strlen(s2+1);
    
            for(i = 0; i <= l1;i ++)
                f[i][0] = 0;
            for(i = 0; i <= l2; i ++)
                f[0][i] = 0;
            for(i = 1; i <= l1; i ++)
            {
                for(j = 1; j <= l2; j ++)
                {
                    if(s1[i] == s2[j])//字符相等时,上一个状态长度加1 
                        f[i][j] = f[i-1][j-1] + 1;
                    else
                    {//字符不等时,取最大的字符序列公共长度 
                        if(f[i-1][j] > f[i][j-1])
                            f[i][j] = f[i-1][j];
                        else
                            f[i][j] = f[i][j-1];
                    }
                }
            }
            printf("%d
    ",f[l1][l2]);
        }

    回溯输出最长上升子序列

    void LCS(char *x,char *y,int n,int m,int a[][N+10],int b[][N+10] )
    {//找到最长公共子序列
        for(i = 0; i <= n; i ++)
            a[i][0] = 0;
        for(j = 0; j <= m; j ++)
            a[0][j] = 0;
        for( i = 1; i <= n; i ++)
            for( j = 1; j <= m; j ++)
            {
                if(x[i-1] == y[j-1])
                {//下标从0开始,故为i-1,j-1。
                    a[i][j] = a[i-1][j-1]+1;
                    b[i][j] = 1; //字符相等标记为1
                }
                else 
                {
                    if( a[i-1][j] > a[i][j-1])
                    {
                        a[i][j] = a[i-1][j] ;
                        b[i][j] = 0;//字符串1大标记为0
                    }
                    else
                    {
                        a[i][j] = a[i][j-1] ;
                        b[i][j] = -1;//字符串2大标记为1
                    }
                }
    
            }
        return;
    }
    void PrintLcs(char *s,int n,int m,int b[][N+10])
    {//回溯输出子序列
        if( 0 == n|| 0 == m)
            return;
        else if( b[n][m] == 1)
        {
            PrintLcs(s,n-1,m-1,b);
            printf("%c",s[n-1]);
        }
        else if( b[n][m] == 0)
            PrintLcs(s,n-1,m,b);
        else if(b[n][m] == -1)
            PrintLcs(s,n,m-1,b);
    }
    
    int main()
    {
        LCS(str1,str2,l1,l2,a,b);
        PrintLcs(str1,l1,l2,b);
        printf("
    ");
        return 0;
    }

    【最大上升子段和】

    /*max_len[N]存1~n各阶段的最大上升子段和*/
    
            max_len[1] = num[1];//数组开始的最大上升子段和是第一个元素  
            max = num[1];//最大上升子段和初始化  
            for( i = 1; i <= n; i ++)  
            {  
                num_len = 0;//记录i左边的最大上升子段和  
                for(j = 1; j < i; j ++)//找到i左边的最大上升子段和  
                {  
                    if(num[i] > num[j])  
                    {  
                        if(num_len < max_len[j])  
                            num_len = max_len[j];  
                    }//if 
                } //for 
                max_len[i] = num_len + num[i]; //i左边最大上升子段和加上自身的值 
                if(max_len[i] > max)  
                    max = max_len[i];  
            }//for  
            printf("%d
    ",max); //输出最大和 

    【连续最大子段和之输出最大子段和,起点,终点】

    时间复杂度为O(n),舍弃数组存储的方法原因有:1:易粗心错估数据范围,2:降低时间复杂度

    #include<stdio.h>  
    
    int max_start,max_end;//最终的起始点和最终的终点 
    int now_start;  //当前起始点 
    int now_sum;  //当前的和 
    int max;//最大子段和 
    int num; //读入当前值 
    
    int main()  
    {  
        int n,i;
        while(scanf("%d",&n)!=EOF)  
        {    
            for(i = 1; i <= n; i ++)  
            {  
                scanf("%d",&num);  
                if( i == 1) //如果是第一个值,初始化数据 
                {  
                    now_sum = max = num;  
                    now_start = max_end = i;  
                }  
                else  
                {  
                    if( now_sum >= 0)  
                        now_sum += num;  
                    else  
                    {  
                        now_sum = num;  
                        now_start = i;  //记录当前起始点 
                    }  
                }  
                if( now_sum >= max) //更新最大值 
                {  
                    max = now_sum;  
                    max_start = now_start; //更新起始点 
                    max_end = i;  //更新终止点 
                }  
            }  
            printf("%d %d %d
    ",max,max_start,max_end);  //输出最大子段和,起始点,终止点 
        }  
        return 0;  
    } 
  • 相关阅读:
    UML统一建模语言笔记
    从零开始学JavaWeb
    也谈微信小程序
    Memcached,你懂的
    一个简单的配置管理器(SettingManager)
    我的AngularJS 学习之旅
    .NET Core 跨平台
    ASP.NET Core 中间件自定义全局异常处理
    面试必考题——递归解题套路
    程序员着装指南
  • 原文地址:https://www.cnblogs.com/hellocheng/p/7350090.html
Copyright © 2011-2022 走看看