题解 P1091 【合唱队形】
看到这题就写了这样一份代码,然后就AC了。
发现题解好像都跟我不一样欸。因为我是乱搞的
研究了半天终于明白了自己是怎么搞得了:
f1[i]
和f2[i]
分别表示以i
为结尾的最长上升子序列和以i
为开头的最长上升子序列。(这点与其他题解无异)
而我的代码与其他题解的不同点就在于:
以求f1[i]
为例
-
其他题解是这样写的:
for(int i=1;i<=n;i++) { for(int j=1;j<i;j++) { if(a[i]>a[j] && f1[j]+1<f1[i]) { f1[i]=f[j]+1; } } }
这样写是用
i
前面的最长上升子序列来更新f1[i]
的值。 -
而我是这样写的:
for(int i=1; i<=n; i++) { for(int j=i+1; j<=n; j++) { if(a[i]<a[j] && f1[i]+1>f1[j]) { f1[j]=f1[i]+1; } } }
这样写则是用
f1[i]
的值来更新i
后面的最长上升子序列的值
而f2
的求法也是同理的。
这就是我AC的原因
CODE:
#include <cstdio>
int n,f1[110],f2[110],a[110];
int main(void) {
scanf("%d",&n);
for(int i=1; i<=n; i++) {
f1[i]=f2[i]=1;
scanf("%d",&a[i]);
}
for(int i=1; i<=n; i++) {
for(int j=i+1; j<=n; j++) {
if(a[i]<a[j] && f1[i]+1>f1[j]) {
f1[j]=f1[i]+1;
}
}
}
for(int i=n; i>=1; i--) {
for(int j=i-1; j>=1; j--) {
if(a[i]<a[j] && f2[i]+1>f2[j]) {
f2[j]=f2[i]+1;
}
}
}
int ans=-0x7fffffff;
for(int i=1; i<=n; i++) {
ans=ans>f1[i]+f2[i]?ans:f1[i]+f2[i];
}
printf("%d",n-ans+1);
return 0;
}