Description
给定一个长度为n的序列(n <= 1000) ,记该序列LIS(最长上升子序列)的长度为m,求该序列中有多少位置不相同的长度为m的严格上升子序列。
Input
先输入一个T,表明下面会有几组数据。
每组数据先输入一个n,表明数组大小。
下面一行有n个数代表该数组,且 1<=a[i]<=n;
每组数据先输入一个n,表明数组大小。
下面一行有n个数代表该数组,且 1<=a[i]<=n;
Output
输出为一行,只需输出上述要求的个数(输出保证结果小于2^31)。
Sample Input
3
2
1 2
4
1 2 4 4
5
1 2 3 4 5
Sample Output
1
2
1
分析:最长不下降自序列的变形,开始做这个题,未考虑的地方是很多的,例如想用桶排去重,却忽略了如果相同元素不连续的状态;改变去重方式,连续去重;寻找位置不同,意味着每个元素它前面的最长序列长度,若元素小于它,则都要累积到它身上,表示到此位置最长不下降子序列的所有可能(位置不同)
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int tt;
scanf("%d",&tt);
while (tt--)
{
int n;
scanf("%d",&n);
int a[1005],c[1005];
int b,t=0;
for (int i=0;i<n;i++) //去重
{
scanf("%d",&b);
if (t!=0 && a[t-1] == b) c[t-1]++;
else a[t]=b,c[t++]=1;
}
int f[1005],g[1005];
memset(g,0,sizeof(g));//累积种类数
f[0]=1;
g[0]=1;
int ans=0;
int Max=0,pos=0;
for (int i=1;i<t;i++)
{
Max=0;
for (int j=0;j<i;j++)//先求出i以前的最长长度
{
if (a[i]>a[j])
{
Max=max(Max,f[j]);
}
}
for (int j=0;j<i;j++)
{
if (a[i] > a[j] && f[j] == Max)
{
if (g[j] == 0) g[j]=1;//初始化
g[i]+=g[j]*c[i];
}
}
f[i]=Max+1;
if (f[i] > ans)
{
ans=f[i];
}
}
int sum=0;
for (int i=0;i<t;i++)
if (f[i] == ans) sum+=g[i];
cout<<sum<<endl;
}
return 0;
}
/**************************************************************
Problem: 1800
User: 1505180117
Language: C++
Result: Accepted
Time:96 ms
Memory:1268 kb
****************************************************************/