题目描述
样例
分析:本题共两问:第一问可以等价为求最大不上升子序列。这样问题就简单了。
首先定义一个i和j。j想对于i更新较快,j<=i。
定义f[i]表示从1到i的最大非上升子序列长度,a[i]为i的高度。如果a[j]>a[i]那么f[i]就可能需要更新所以f[i]=max(f[i],f[j]+1);

1 for(int i=1;i<=n;i++){ 2 f[i]=1; //一定不要忘记第一个也算一个 3 for(int j=1;j<i;j++){ 4 if(h[i]<=h[j]) f[i]=max(f[i],f[j]+1); 5 } 6 maxx=max(maxx,f[i]); 7 }
第二问我一开始想的是用多次求最长不上升子序列,但这个想法显然是错的比如“7 5 4 1 6 3 2”用多次求最长不上升序列所有为”7 5 4 3 2”,
”1”,”6”共3套系统;但其实只要2套,分别为:”7 5 4 1”与”6 3 2”。
正确做法(还有一种做法,效率(n2),超时了,就不说了)第二问的,我们需要用到Dilworth定理:最少链划分=最长反链长度

for(int i=1;i<=n;i++){ g[i]=1; for(int j=1;j<i;j++){ if(h[i]>h[j]) //求最长上升子序列的长度 g[i]=max(g[i],g[j]+1); } mixn=max(mixn,g[i]); }

#include<bits/stdc++.h> using namespace std; const int L=200+100; int n=1,h[L],a[L],f[L],g[L],maxx=-11111111,mixn=-11111111; int main(){ while (scanf("%d",&h[n])!=EOF) n++; n--; for(int i=1;i<=n;i++){ f[i]=1; //记录第i个前面的最长不上升子序列的长度 for(int j=1;j<i;j++){ if(h[i]<=h[j]) f[i]=max(f[i],f[j]+1); } maxx=max(maxx,f[i]); } for(int i=1;i<=n;i++){ g[i]=1; for(int j=1;j<i;j++){ if(h[i]>h[j]) //求最长上升子序列的长度 g[i]=max(g[i],g[j]+1); } mixn=max(mixn,g[i]); } printf("%d %d ",maxx,mixn); return 0; }