最长上升子序列算法以及代码实现

//1.动态规划最长升序子序列问题 问题可能会出现多解分支 由于大脑爆炸写不出来 只给出一组最优解 
//2.不能用VS运行 由于定义result[sum] VS无法判断sum是否为常数 
//3.由于C语言不能定义未知数组 文件开始用define声明变量 需要手动替换10 50 500 

//4.多处由于调试注释掉 保留痕迹 仿造最长公共子序列方法实现 时间复杂度O(N2)
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define NUMBER 10
//#define NUMBER 50
//#define NUMBER 500 

int data[NUMBER+1][NUMBER+1];//外部定义 不然达到414以上DEV崩溃 
int flag[NUMBER+1][NUMBER+1]={0};//外部定义 不然达到414以上DEV崩溃 
void printResult(int flag[][NUMBER+1],int x[],int n,int flagi,int flagj,int sum){//打印结果 
    int result[sum+1];
    int i=flagi,j=flagj;
    int m=sum;
    while(m>1){
        
        if(flag[i][j]==1){
            i--;
        }
         
        else{
            result[m]=x[j-1];
            m--;
            j=i;
        }
        
    }
    result[1]=x[j-1];
    printf("最优解为:\n");
    for(int m=1;m<=sum;m++){//输出最优解 
        printf("%d ",result[m]);
    }
}
void MaxLength(int *x,int n){
    int i,j;
    //int data[NUMBER+1][NUMBER+1];//外部定义 不然达到414以上DEV崩溃 
    //int flag[NUMBER+1][NUMBER+1]={0};//外部定义 不然达到414以上DEV崩溃 
    for(i=1;i<=n;i++){//把最上排和最左列初始化为0
        data[i][0]=0;
        data[0][i]=0;
    }
    data[0][0]=0;
    for(i=1;i<=n;i++){//行
        data[i][0]=data[0][i];
        for(j=i;j<=n;j++){//列
            if(x[j-1]<=x[i-1]){
                data[i][j]=data[i-1][j];
                flag[i][j]=1;//1代表从上一个i继承来的 这个数不能参与构成序列 直接继承当前序列 
            }
            else{
                if(data[i-1][j]>data[i][0]+1){
                    data[i][j]=data[i-1][j];
    
                    flag[i][j]=1;//1代表从上一个i继承来的 即由x[i]的参与组成的新序列没有当前序列的长 直接继承当前序列  
                }
                 
                 
                else{
                    data[i][j]=data[i][0]+1;
                    data[0][j]=data[i][j];
                    flag[i][j]=2;//2代表从左边来的  即出现了更长的序列替代了当前序列 
                }
            } 
        } 
    /*for(int m=0;m<=n;m++){
        for(int k=0;k<=n;k++){
            if(k<m&&k!=0) printf("x\t");
            else if(k==0) printf("%d\t",data[m][k]);
            else printf("%d\t",data[m][k]);
        }
        printf("\n");
    }
    printf("\n\n\n\n");*/
    }
    /*for(i=0;i<=n;i++){//输出动态长度值 
        for(j=0;j<=n;j++){
            if(j<i&&j!=0) printf("x\t");
            else if(j==0) printf("%d\t",data[i][j]);
            else printf("%d\t",data[i][j]);
        }
        printf("\n");
    } 
    printf("\n\n\n");*/
    /*for(i=0;i<=n;i++){//输出遍历痕迹 
        for(j=0;j<=n;j++){
            printf("%d\t",flag[i][j]);
        }
        printf("\n");
    }*/
    int sum=0,flagi=0,flagj=0;
    for(i=1;i<=n;i++){
        for(j=i;j<=n;j++){
            if(sum<=data[i][j]){
                sum=data[i][j];
                flagi=i;//定位最长序列的最后一位 
                flagj=j;
            }
        }
    }
    //printf("\n\n\n");
    //printf("%d %d\n",flagi,flagj);//输出最优解序列的最后一个数的位置 
    printf("所找出的最优解长度为:\n%d\n",sum+1);//输出最优解长度 由于第一个数没算长度 结果加一 
    printf("\n\n\n");
    printResult(flag,x,NUMBER,flagi,flagj,sum+1);
}

int main(){
    srand(time(NULL));
    int x[NUMBER];
    for(int i=0;i<NUMBER;i++){
        x[i]=rand()%NUMBER;
    }
    printf("产生的随机数序列为:\n ");
    for(int i=0;i<NUMBER;i++){//输出产生的随机数序列 
        printf("%d\t",x[i]);
    }
    printf("\n\n\n");
    //int data[NUMBER+1][NUMBER+1];//外部定义 不然达到414以上DEV崩溃 
    MaxLength(x,NUMBER);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值