题目描述:
给定一个1--n乱序的标准序列
输入另一个待求1--n序列,求解到底待求序列中最大有多长的连续的数,符合标准序列的相对顺序。
例如: 2 4 1 3 5
3 1 4 5 2
答案:2(4,5或1,5或3,5)
算法描述:
一、这到问题关键是在于思维:因为要考虑到所有情况是不可能的,有因为在乱序上不好做操作,所以要做预处理:
1、第一种,将标准序列做变换,变成1234....n,记录变化方式,对后续待求序列做相同变换(程序一)
2、第二种,对于标准序列中的每个数字按顺序设置权重,对待求序列用对应权重生成新序列(程序二)
二、最后求一个最长上升子序列即可。
三、输入很难处理
代码一:
#include<stdio.h> #include<string.h> #define maxn 25 int n; char s[maxn*5]; int p[maxn];//存储第i个数应该换到p1[i]的位置上 int num[maxn];//放置数字序列 int anp[maxn];//求LIS的序列 int string_scanf(int i)//返回字符串中的第i个数字 { int t=0; int p=0; while (p<strlen(s)){ int nu=s[p]-'0'; if (s[p+1]<='9' && s[p+1]>='0') {nu=nu*10+s[p+1]-'0';p+=3;} else p+=2; t++; if (t==i) return nu; } } void getnum(){//string->num for(int i=1;i<=n;i++) num[i]=string_scanf(i); } void init(){//生成应该置换的序列 getnum(); for(int i=1;i<=n;i++){ p[i]=num[i]; } } int LIS() { int dp[maxn]; int ans=1; for(int i=1;i<=n;i++){ dp[i]=1; for(int j=1;j<=i;j++){ if(anp[i]>anp[j] && dp[i]<dp[j]+ 1){ dp[i]=dp[j]+1; if(dp[i]>ans){ ans=dp[i]; } } } } return ans; } int slove(){ getnum(); for(int i=1;i<=n;i++){ anp[p[i]]=num[i]; } for(int i=1;i<=n;i++) return LIS(); } int main(){ while(gets(s)){//读写部分 if (strlen(s)<=2){ n=s[0]-'0'; if (s[1]!=' ') n=n*10+s[1]-'0'; gets(s); init(); }else {printf("%d ",slove());} } return 0; }