版权声明:转载请注明原出处啦QAQ(虽然应该也没人转载): https://blog.csdn.net/hzk_cpp/article/details/89432228
题目:POJ3700.
题目大意:给定一个长度为
的序列
(互不相同),现在要求把序列划分成数量最少的子序列(不能重复且不能有剩余),使得每个子序列递增或递减.
.
刚看到的时候以为可以用DP做,然后看到题目中的每个子序列可以递增也可以递减和数据范围…果断搜索!
怎么搜?考虑每次记录两种不同个子序列,每个子序列都记录一下最后一个值,然后大力枚举把当前数添加到哪里.
发现这个算法有些慢,所以可以贪心地思考一下,在递增(递减)的子序列中,把当前数加在一个尽量大(小)的数后面肯定不会更差,所以每次只在两种不同的子序列中考虑最后一个数尽量大(小)的数即可,这可以大大加快程序的速度.
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=50,INF=(1<<31)-1;
int up[N+9],dn[N+9],tu,td;
int a[N+9],n,ans;
void dfs(int k){
if (tu+td>=ans) return;
if (k>n) {ans=tu+td;return;}
int tmp=0,last;
for (int i=1;i<=tu;++i)
if (up[i]>up[tmp]&&up[i]<a[k]) tmp=i;
last=up[tmp];
tmp==0?up[++tu]=a[k]:up[tmp]=a[k];
dfs(k+1);
tmp==0?--tu:up[tmp]=last;
tmp=0;
for (int i=1;i<=td;++i)
if (dn[i]<dn[tmp]&&dn[i]>a[k]) tmp=i;
last=dn[tmp];
tmp==0?dn[++td]=a[k]:dn[tmp]=a[k];
dfs(k+1);
tmp==0?--td:dn[tmp]=last;
}
Abigail into(){
for (int i=1;i<=n;++i)
scanf("%d",&a[i]);
}
Abigail work(){
ans=n;
up[0]=0;dn[0]=INF;
dfs(1);
}
Abigail outo(){
printf("%d\n",ans);
}
int main(){
while (~scanf("%d",&n)&&n){
into();
work();
outo();
}
return 0;
}