动态规划求解合唱队问题的思路

动态规划求解合唱队问题思路:


该题的关键是不能置换队员的顺序,这个要求降低了问题的难度,如果可以排列的话就难了,建一个堆总会出现重复的元素,如何调整还没想出来怎么做。

考虑不能排列的情况,先对整个队列求一个最长递增子序列再求一个最长递降子序列。则剩下的人数就好算了。因为最长递增子序列是一个典型的动态规划问题,设子问题的解是FAscend[i]和FDescend[i]则合唱队问题的最优解是N-max[i]{FAscend[i]+ FDescend[i]-1}

关键:最优子结构的性质,递归定义子问题的解,自底向上求解

一, 最长递增子序列问题的描述:设L=是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=,其中k1<k2<…<km且aK1<ak2<…<akm。求最大的m值。

二, 最长递增子序列问题的最优子结构性质:

设f(i)表示序列中以ai为末尾元素的最长递增子序列的长度。注意此处,f(i)只表示一个长度,而并没有包含是哪个具体的序列,这是动态规划的一个显著特征。需要求是具体哪个序列需要回溯求解。

在求以ai为末尾的最长递增子序列时,找到所有序号在L前面且小于ai的元素aj,即j<i,且aj<ai。

如果这样的元素存在,那么对于所有的aj,都有一个以aj为末尾元素的最长递增子序列的长度,把其中最大的f(j)选出来,那么f(i)就等于最大的f(j)+1,即f(i)=max[j]{f(j)+1},即以ai为末尾元素的最长递增子序列,等于以使f(j)最大的哪个aj为末尾元素的递增子序列最末再加上ai;

如果这样的元素不存在,那么ai自身构成一个长度为1的以ai为末尾元素的递增子序列。因为f(i)表示的长度必须以ai为末尾。

三, 实现:用f【】来保存最优值,外层循环扩大问题规模,即数组f的下表递增,内层循环遍历从i到1的子问题的最优值。

初始值f【1】=1。

合唱队问题是一个经典的动态规划问题。假设有一支合唱队,由N个人组成,每个人的身高不同。现在要求将这支合唱队分成两个部分,左边为递增子序列,右边为递减子序列,且两个部分的人数之和最大。 解决这个问题的关键是找到最长的递增子序列和最长的递减子序列。首先,可以使用动态规划求解最长递增子序列的长度。定义一个数组dp1,其中dp1[i]表示以第i个人结尾的最长递增子序列的长度。初始时,将dp1数组中的每个元素初始化为1。 然后,从第二个人开始遍历到第N个人,对于每个人i,遍历其前面的所有人j(j从1到i-1),如果第j个人的身高小于第i个人的身高,并且dp1[j]+1大于dp1[i],则更新dp1[i]=dp1[j]+1。 接下来,可以使用类似的方法求解最长递减子序列的长度。定义一个数组dp2,其中dp2[i]表示以第i个人开头的最长递减子序列的长度。同样地,将dp2数组中的每个元素初始化为1。 从倒数第二个人开始遍历到第一个人,对于每个人i,遍历其后面的所有人j(j从i+1到N),如果第j个人的身高小于第i个人的身高,并且dp2[j]+1大于dp2[i],则更新dp2[i]=dp2[j]+1。 最后,遍历每个人,计算dp1[i]+dp2[i]-1的最大值,就是可以分成两个部分的合唱队形的最大人数。 这就是使用动态规划解决合唱队问题的基本思路。希望能对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值