附上代码,又是一篇C语言题解
#include<stdio.h>
int max(int x,int y)//返回最大值的函数
{
return (x > y) ? x : y;
}
int main()
{
int n;
scanf("%d",&n);
int a[n];
for(int i = 0;i < n;i++)
scanf("%d",&a[i]);
int dp1[n];//以a数列中第个元素i结尾的最长上升子序列
int dp2[n];//以a数列中第i个元素开头的最长下降子序列
int result[n];//储存以i作为最高点的符合要求的数组长度
dp1[0] = 1;//原理同下
dp2[n - 1] = 1;//i从n-2开始,不能对dp2[n-1]初始化,便在此初始化
for(int i = n - 2;i >= 0;i--)//计算从i开始的最长递减子序列长度
{
dp2[i] = 1;//若只有一个元素组成下降序列,序列长度为一
for(int p = i + 1;p < n;p++)//a[p]在a[i]的后面
{
if(a[i] > a[p])//检查dp2[i]在自己原先的数列中和与
//dp2[p]所在的数列组合那个更长,选取长的
dp2[i] = max(dp2[i],dp2[p] + 1);
}
}
for(int i = 1;i < n;i++)//计算以i为结尾的最长递增序列长度
{
dp1[i] = 1;//计算原理与上述最长下降序列相同
for(int p = i - 1;p >= 0;p--)
{
if(a[i] > a[p])
dp1[i] = max(dp1[i],dp1[p] + 1);
}
}
int maximum = 0;//答案所求的最长队伍的长度
for(int i = 0;i < n;i++)
{
result[i] = dp1[i] + dp2[i] - 1;
//减一是因为上升序列和下降序列相加后会把中间的元素计算两遍
maximum = max(maximum,result[i]);
}
printf("%d",n - maximum);//n-maximum是需要剔除的人数
return 0;
}
删除线格式
这道题需要运用最长上升子序列和最长下降子序列的知识,
这两个都需要用动态规划求解,与基本序列不同的是,一个需要以第i个数作为结尾,另一个需要将其作为开头。
在计算最长序列长度的时候,要逐一初始化,若不初始化,相当于认为 “一个数字组成的序列长度为0” ,这样就会使最长的序列比正确值少一。
还有一点需要注意,即在计算数组result的时候,**要注意是对应的最长上升序列和下降序列之和减一,**不然会有重复计算,导致结果多一个人。
这道题,在直到最长递增序列的求法之后,加以适度变形,就可以AC了。
删除线格式
溜了溜了~~