动态规划之合唱队形问题(最长递增子序列变形)
2016-08-14 21:01
375 查看
http://blog.csdn.net/hulifangjiayou/article/details/48108587
题目描述
N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学不交换位置就能排成合唱队形。
合唱队形定义:设K位同学从左到右依次编号为1, 2, …, K,他们的身高分别为T1, T2, …, TK,
则他们的身高满足T1 < T2 < … < Ti, Ti > Ti+1 > … > TK (1 <= i <= K)。
要求:已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
输入
输入的第一行是一个整数N,表示同学的总数。
第一行有n个整数,用空格分隔,第i个整数Ti是第i位同学的身高(厘米)。
输出
输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。
解题思路
定义n位同学的身高数组为a
(注意这里数组长度不允许为变量,这里只是为了理解将n写如到[]中)。
【总体思路】:假设第i(0<= i <= n - 1)个同学为最高点,分别求出此时i左边的最长递增子序列长度inc1[i],i右边的最长递减子序列长度inc2[i],由于最高点i同时包括在了inc1[i]和inc2[i]之中,因此实际的合唱队形的长度为inc1[i] + inc2[i] - 1。而我们求得的最后结果就是i从1到n - 1中,使得inc1[i] + inc2[i]
- 1最大的情况。
【具体实现】:现在设i为下标,循环i从0到n-1,求得各种i值对应的inc1[i];循环i从0到n-1,求得各种i值对应的inc2[i]。最后循环i从0到n-1,求得各种i值对应的inc[i] + inc2[i] - 1最大的情况ans,然后n - ans即为出列同学的人数。
当i = 0的时候,最高点0左边只有它自己,因此inc1[0] = 1;当i = n - 1的时候,最高点n - 1右边只有它自己,因此inc2[n - 1] = 1;当i处于0到n - 1之间时的求法也很好理解,在求inc1[i]时,j = (0 ~ i - 1)的inc[j]已经得出来了,所以我们只需要比较在前面的这些序列中加上a[i]时的最长递增序列,即在a[i]大于前面这些序列值的情况下inc[j] + 1最大的情况即为inc[i]。
源代码如下
题目描述
N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学不交换位置就能排成合唱队形。
合唱队形定义:设K位同学从左到右依次编号为1, 2, …, K,他们的身高分别为T1, T2, …, TK,
则他们的身高满足T1 < T2 < … < Ti, Ti > Ti+1 > … > TK (1 <= i <= K)。
要求:已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
输入
输入的第一行是一个整数N,表示同学的总数。
第一行有n个整数,用空格分隔,第i个整数Ti是第i位同学的身高(厘米)。
输出
输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。
解题思路
定义n位同学的身高数组为a
(注意这里数组长度不允许为变量,这里只是为了理解将n写如到[]中)。
【总体思路】:假设第i(0<= i <= n - 1)个同学为最高点,分别求出此时i左边的最长递增子序列长度inc1[i],i右边的最长递减子序列长度inc2[i],由于最高点i同时包括在了inc1[i]和inc2[i]之中,因此实际的合唱队形的长度为inc1[i] + inc2[i] - 1。而我们求得的最后结果就是i从1到n - 1中,使得inc1[i] + inc2[i]
- 1最大的情况。
【具体实现】:现在设i为下标,循环i从0到n-1,求得各种i值对应的inc1[i];循环i从0到n-1,求得各种i值对应的inc2[i]。最后循环i从0到n-1,求得各种i值对应的inc[i] + inc2[i] - 1最大的情况ans,然后n - ans即为出列同学的人数。
当i = 0的时候,最高点0左边只有它自己,因此inc1[0] = 1;当i = n - 1的时候,最高点n - 1右边只有它自己,因此inc2[n - 1] = 1;当i处于0到n - 1之间时的求法也很好理解,在求inc1[i]时,j = (0 ~ i - 1)的inc[j]已经得出来了,所以我们只需要比较在前面的这些序列中加上a[i]时的最长递增序列,即在a[i]大于前面这些序列值的情况下inc[j] + 1最大的情况即为inc[i]。
源代码如下
#include <iostream> #include <stdio.h> using namespace std; int inc1[200],inc2[200],a[200]; //inc1-->longest increase array from head to tail //inc2-->longest increase array from tail to head int main() { int n; while(scanf("%d",&n)!=EOF) { int ans=0,i,j; for(i = 0; i < n; i++) //输入n个人的身高 scanf("%d",&a[i]); //inc1[i]是存储以i为最高点时左边的递增子序列长度 inc1[0]=1; for(i = 1; i < n; i++) { inc1[i] = 1; for(j = 0; j < i; j++) if(a[i] > a[j] && inc1[j] + 1 > inc1[i]) inc1[i] = inc1[j]+1; } //inc2[i]是存储以i为最高点时左边的递减子序列长度 inc2[n - 1] = 1; for(i = n - 2; i >= 0; i--) { inc2[i] = 1; for(j = n - 1; j > i; j--) if(a[j] < a[i] && inc2[j] + 1 > inc2[i]) inc2[i] = inc2[j] + 1; } for(i = 0; i<=n; i++) if(inc1[i] + inc2[i]-1 > ans) ans = inc1[i] + inc2[i] - 1; printf("%d\n",n-ans); } return 0; }
相关文章推荐
- 动态规划之合唱队形问题(最长递增子序列变形)
- 动态规划之合唱队形问题(最长递增子序列变形)
- 动态规划 最长递增子序列 oj合唱团问题
- 华为训练题目:初级——合唱队(递增子序列,DP动态规划问题)
- 最大连续子序列和,乘积,最长递增子串,最长公共子串,子序列等问题(动态规划等)
- 动态规划之最长递增子序列 最长不重复子串 最长公共子序列
- 动态规划 (Dynamic Programming) 之 最长递增子序列(Longest Increase Subsequence)
- 动态规划---最长上升子序列问题(O(nlogn),O(n^2))
- 动态规划之合唱队形问题
- 动态规划之最长上升自序列问题
- 动态规划 - 最长公共子序列 - 最长公共子串 - 最长不重复子串 - 最长递增子序列 - 最长回文子串
- 动态规划——最长上升子序列问题(LIS)
- 动态规划之合唱队形问题
- 动态规划之最长递增子序列(思路)
- 动态规划问题学习路线:斐波那契数列,最大递增子序列,松鼠捡苹果,最大公共子序列,字符串编辑距离
- 经典动态规划问题--最长上升子序列 POJ--2533
- 动态规划-最长递增序列(LIS)【模板】
- HDU1069 Monkey and Banana(dp动态规划,最长非递减子序列变形题)
- 动态规划6:最长递增子序列问题
- 矩形嵌套--动态规划--最长递增子序列问题变形