//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);
}