C++ 合唱队排队问题 - 统计初始队形数量
C++ 合唱队排队问题 - 统计初始队形数量
问题描述:
为了在即将到来的晚会上有更好的演出效果,作为 AAA 合唱队负责人的小 A 需要将合唱队的人根据他们的身高排出一个队形。假定合唱队一共 n 个人,第 i 个人的身高为 h_i 米 (1000 ≤ h_i ≤ 2000),并已知任何两个人的身高都不同。假定最终排出的队形是 A 个人站成一排,为了简化问题,小 A 想出了如下排队的方式:他让所有的人先按任意顺序站成一个初始队形,然后从左到右按以下原则依次将每个人插入最终排出的队形中:
- 第一个人直接插入空的当前队形中。
- 对从第二个人开始的每个人,如果他比前面那个人高 (h 较大),那么将他插入当前队形的最右边。如果他比前面那个人矮 (h 较小),那么将他插入当前队形的最左边。
当 n 个人全部插入当前队形后便获得最终排出的队形。
例如,有 6 个人站成一个初始队形,身高依次为 1850, 1900, 1700, 1650, 1800, 1750, 那么小 A 会按以下步骤获得最终排出的队形:
- 1850
- 1850, 1900,因为 1900 > 1850
- 1700, 1850, 1900,因为 1700 < 1900
- 1650, 1700, 1850, 1900,因为 1650 < 1700
- 1650, 1700, 1850, 1900, 1800,因为 1800 > 1650
- 1750, 1650, 1700, 1850, 1900, 1800,因为 1750 < 1800
因此,最终排出的队形是 1750, 1650, 1700, 1850, 1900, 1800。
小 A 心中有一个理想队形,他想知道多少种初始队形可以获得理想的队形。
请求出答案对 1965082719650827 取模的值。
算法思路:
- 题目中的插入操作可以看做是不断地将一个数插入一个已经排好序的序列中,可以想到使用插入排序的思想。
- 我们从左到右遍历初始队形,对于每个人,我们需要找到最长的递增子序列和最长的递减子序列,然后将这个人插入到这两个子序列中的一个,使得插入后这两个子序列的长度之和最大(因为这样可以保证插入的次数最少)。
- 插入的时候,如果插入到递增子序列中,则从后往前找到第一个比它小的数,插入到这个数的后面;如果插入到递减子序列中,则从后往前找到第一个比它大的数,插入到这个数的前面。
C++ 代码:
// ... 代码 ...
原文地址: http://www.cveoy.top/t/topic/nMup 著作权归作者所有。请勿转载和采集!