题目链接
对题干进行刨析,就是输入多组数据,求每组数据可拆分成严格单调上升子序列与严格单调下降子序列之和最小,如果直接沿用最长上升子序列模板的话,是不合适的,我们需要对模板进行优化,up[k]储存第k组上升子序列的末尾元素,down[k]储存第k组下降子序列的末尾元素。在整个过程中,我们先枚举每个数,先枚举将该数放到up[]中,还是down[]中,如果放到up[]中,则枚举该数到底要放到哪组上升序列后面,反之,枚举该数放到哪组下降序列后面。但是再拓展节点时存在贪心策略,降低了时间。
再此附上一瞬流年丶涅槃的代码
#include<iostream>
using namespace std;
const int N = 55;
int a[N], ans, up[N], down[N], n;
void dfs(int u, int d, int t) //u表示上升的系统个数,d表示下降的系统个数,t表示第t个数
{
if(u + d >= ans) return ;
if(t == n){
if(u + d < ans)ans = u + d;
return ;
}
int i;
for(i = 1; i <= u; i++) //找到第一个末尾数小于a[t]的导弹系统
if(up[i] < a[t])break;
int temp = up[i];
up[i] = a[t];//添加到该导弹系统中
dfs(max(u, i), d, t + 1);
up[i] = temp; //恢复现场
for(i = 1; i <= d; i++)//找到第一个末尾数大于a[t]的导弹系统
if(down[i] > a[t])break;
temp = down[i];
down[i] = a[t];//添加到该导弹系统中去
dfs(u, max(d, i), t + 1);
down[i] = temp;//恢复现场
}
int main()
{
while(scanf("%d", &n) != EOF && n != 0){
ans = 100;
for(int i = 0; i < n; i++)
cin >> a[i];
dfs(0, 0, 0);
printf("%d\n", ans);
}
return 0;
}
作者:一瞬流年丶涅槃
链接:https://www.acwing.com/solution/content/4010/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。