【tyvj1208】最长不下降子序列2

来源:互联网 发布:windows sdk v8.1下载 编辑:程序博客网 时间:2024/05/01 01:12

描述

设有整数序列b1,b2,b3,…,bm,若存在i1<i2<i3<…<in,且bi1<bi2<bi3<…<bin,则称 b1,b2,b3,…,bm中有长度为n的不下降序列bi1,bi2,bi3,…,bin。求序列b1,b2,b3,…,bm中所有长度(n)最大不下降子序列
具有相同元素的序列,我们称之为重复序列,这里我们不统计重复序列,也即是说,重复的是算一次

输入格式

第一行为m,表示m个数(m<=900)
第二行m个数

输出格式

第一行输出最大长度n
第二行输出长度为n的序列个数Total

测试样例1

输入


1 2 2

输出


1
【题解】

题目描述的是最长上升子序列

至今仍然觉得这道题的思路很奇怪。在序列的后面加一个极大的数,其实这是用来存答案的。然后做最长上升,做完之后寻找答案的过程其实还是一个dp,由前面的点去扩展后面的点。但是要注意的是,如果当前点和后面有一个点重复,那么直接退出防止多算(因为对于后面的数来说,前面有两个一样的是没有影响的)

其实也就是说用离他最近的那一个符合条件的点去扩展他。

要注意不能把相同的数的前面那个删去。反例比如说13235。但是把相邻的相同的数删掉是完全可以的。

这道题隔一段时间应该看一看。但是还是觉得时间复杂度十分的不科学

【代码】

#include<iostream>#include<cstring>#include<cstdio>#include<map>#define inf 2100000000using namespace std;int n1,n,Max;int f[1005],a[1005],h[1005],ans[1005];bool b[1005];int main(){scanf("%d",&n1);for (int i=1;i<=n1;++i) scanf("%d",&a[i]);for (int i=2;i<=n1;++i)  if (a[i]==a[i-1]) b[i]=true;n=0;for (int i=1;i<=n1;++i)  if (!b[i]) h[++n]=a[i];h[++n]=inf;f[1]=1;for (int i=2;i<=n;++i){for (int j=1;j<i;++j)  if (h[i]>h[j]&&f[i]<f[j])  f[i]=f[j];f[i]++;}for (int i=1;i<=n;++i)  Max=max(f[i],Max);for (int i=1;i<=n;++i) if (f[i]==1) ans[i]=1;for (int i=1;i<=Max;++i)  for (int j=i;j<=n;++j)    if (f[j]==i)      for (int k=j+1;k<=n;++k){      if (f[k]==f[j]+1&&h[k]>h[j])        ans[k]+=ans[j];      if (h[k]==h[j]) break;      }Max--;printf("%d\n%d\n",Max,ans[n]);}


0 0
原创粉丝点击