洛谷 P1091 合唱队形 C语言

附上代码,又是一篇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了。
删除线格式
溜了溜了~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值