题解 P2896 【[USACO08FEB]一起吃饭Eating Together】
在题目中可以得出:
只用找一次最长不上升序列 再找一次最长不下降序列 记录下长度 用总数减去较大的那个就好了
代码也很简单:
#include<iostream>
#include<cmath>
using namespace std;
int n,s,a[30005],f[30005],f1[30005];
int main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++){
if(a[i]>=a[j])
f[i]=max(f[i],f[j]);
}
f[i]++;
}//最长不下降序列
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++){
if(a[i]<=a[j])
f1[i]=max(f1[i],f1[j]);
}
f1[i]++;
}//最长不上升序列
for(int i=1;i<=n;i++){
s=max(s,f[i]);
s=max(s,f1[i]);
}//取最长
cout<<n-s;
return 0;
}
仔细观察(也不用很仔细)
就能发现卡片上的数字只有
于是 可以将内层倒序循环 如果找到数字相同那么前面就不用找了 因为前面已经处理过了
#include<iostream>
#include<cmath>
using namespace std;
int n,s,a[30005],f[30005],f1[30005];
int main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++){
for(int j=i-1;j>0;j--){
if(a[i]>=a[j])
f[i]=max(f[i],f[j]);
if(a[i]==a[j])break;//前面已经被处理过可以跳过
}//内层倒序循环
f[i]++;
}//最长不下降序列
for(int i=1;i<=n;i++){
for(int j=i-1;j>0;j--){
if(a[i]<=a[j])
f1[i]=max(f1[i],f1[j]);
if(a[i]==a[j])break;
}
f1[i]++;
}//最长不上升序列
for(int i=1;i<=n;i++){
s=max(s,f[i]);
s=max(s,f1[i]);
}
cout<<n-s;
return 0;
}
补一句:
这个方法最长不上升序列、最长不下降序列、最长上升序列、最长下降序列都可以用,但数据重复率较高的效果更明显一些。