。。。

导航

【动态规划】【子序列模板】

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\n",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("\n");
    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\n",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\n",max,max_start,max_end);  //输出最大子段和,起始点,终止点 
    }  
    return 0;  
} 

posted on 2017-07-31 18:45  大学僧  阅读(173)  评论(0编辑  收藏  举报