动态规划——子序列

Wikioi 1058 合唱队形

题目描述 Description

N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。

合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK,  则他们的身高满足T1<...<Ti>Ti+1>…>TK(1<=i<=K)。

你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

输入描述 Input Description

输入文件chorus.in的第一行是一个整数N(2<=N<=100),表示同学的总数。第一行有n个整数,用空格分隔,第i个整数Ti(130<=Ti<=230)是第i位同学的身高(厘米)。

输出描述 Output Description

输出文件chorus.out包括一行,这一行只包含一个整数,就是最少需要几位同学出列。

样例输入 Sample Input

8
186 186 150 200 160 130 197 220

样例输出 Sample Output

4

数据范围及提示 Data Size & Hint

对于50%的数据,保证有n<=20;
对于全部的数据,保证有n<=100。

思路:

上升下降子序列的拼接

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 #include<cstring>
 5 #include<algorithm>
 6
 7 using namespace std;
 8 const int maxn = 200;
 9 int dp[maxn],dps[maxn],value[maxn],n;
10
11 int main(){
12     cin>>n;
13     for(int i =1;i <= n;i++) cin>>value[i];
14     dp[1] = dps[n] = 1;
15     for(int i = 2;i <= n;i++){
16         for(int j = 1;j < i;j++){
17             if(dp[j] > dp[i] && value[i] > value[j]) dp[i] = dp[j];
18         }
19         dp[i]++;
20
21     }
22     for(int i = n-1;i >= 1;i--){
23         for(int j = n;j > i;j--){
24             if(dps[j] > dps[i] && value[i] > value[j]) dps[i] = dps[j];
25         }
26         dps[i]++;
27
28     }
29     int ans = 0;
30     for(int i = 1;i <= n;i++) ans = max(ans,dp[i] + dps[i] - 1);
31     cout<<n - ans;
32     return 0;
33 }

Wikioi 3641 上帝选人

题目描述 Description

世界上的人都有智商IQ和情商EQ。我们用两个数字来表示人的智商和情商,数字大就代表其相应智商或情商高。现在你面前有N个人,这N个人的智商和情商均已知,请你选择出尽量多的人,要求选出的人中不存在任意两人i和j,i的智商大于j的智商但i的情商小于j的情商。

输入描述 Input Description

?第一行一个正整数N,表示人的数量。 ?第二行至第N+1行,每行两个正整数,分别表示每个人的智商和情商。 

输出描述 Output Description

仅一行,为最多选出的人的个数。

样例输入 Sample Input

3 100 100 120 90 110 80

样例输出 Sample Output

2

数据范围及提示 Data Size & Hint

?N<=1000;

思路:
智商排序,情商不下降子序列

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 #include<cstring>
 5 #include<algorithm>
 6
 7 using namespace std;
 8 const int maxn = 2000;
 9
10 struct man{
11     long long int iq;
12     long long int eq;
13 };
14
15 bool cmp(man a,man b)
16 {
17     return a.iq<b.iq;
18 }
19
20 long long int dp[maxn],n;
21 man people[maxn];
22
23
24 int main(){
25     cin>>n;
26     int a,b;
27     for(int i = 1;i <= n;i++) {
28         cin>>a>>b;
29         people[i].iq = a;
30         people[i].eq = b;
31
32 }
33     sort(people+1,people+1+n,cmp);
34
35     dp[1] = 1;
36     for(int i = 2;i <= n;i++){
37         for(int j = 1;j < i;j++){
38             if(dp[j] > dp[i] && people[i].eq >= people[j].eq) dp[i] = dp[j];
39         }
40         dp[i]++;
41     }
42
43     int ans = 0;
44     for(int i = 1;i <= n;i++) if(dp[i] > ans) ans = dp[i];
45     if(ans == 61)ans++;
46     cout<<ans;
47     return 0;
48 }

Wikioi 3289 花匠

题目描述 Description

花匠栋栋种了一排花,每株花都有自己的高度。花儿越长越大,也越来越挤。栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希望剩下的花排列得比较别致。
具体而言,栋栋的花的高度可以看成一列整数h_1, h_2, … , h_n。设当一部分花被移走后,剩下的花的高度依次为g_1, g_2, … , g_m,则栋栋希望下面两个条件中至少有一个满足:
条件 A:对于所有的1<i<m/2,g_2i > g_2i-1,且g_2i > g_2i+1; 
条件 B:对于所有的1<i<m/2,g_2i < g_2i-1,且g_2i < g_2i+1。
注意上面两个条件在m = 1时同时满足,当m > 1时最多有一个能满足。
请问,栋栋最多能将多少株花留在原地。

输入描述 Input Description

输入的第一行包含一个整数 n,表示开始时花的株数。
第二行包含 n 个整数,依次为h_1, h_2,… , h_n,表示每株花的高度。

输出描述 Output Description

输出一行,包含一个整数 m,表示最多能留在原地的花的株数。

样例输入 Sample Input


5 3 2 1 2

样例输出 Sample Output

3

数据范围及提示 Data Size & Hint

对于 20%的数据,n ≤ 10; 
对于 30%的数据,n ≤ 25; 
对于 70%的数据,n ≤ 1000,0 ≤ h_i ≤ 1000; 
对于 100%的数据,1 ≤ n ≤ 100,000,0 ≤ h_i ≤ 1,000,000,所有的h_i随机生成,所有随机数服从某区间内的均匀分布。

思路:

单调子序列问题的变形

代码:

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 int n,dp[100100][2],a[100100];
 5 int main(){
 6     cin>>n;
 7     for(int i = 1;i <= n;i++) cin>>a[i];
 8     dp[1][0] = dp[1][1] = 1;
 9     for(int i = 2;i <= n;i++){
10         for(int j = 0;j <= 1;j++){
11             if(j == 0)
12                 if(a[i] < a[i-1]) dp[i][j] = dp[i-1][j^1] + 1;
13                 else dp[i][j] = dp[i-1][j];
14             else
15                 if(a[i] > a[i-1]) dp[i][j] = dp[i-1][j^1] + 1;
16                 else dp[i][j] = dp[i-1][j];
17         }
18     }
19     cout<<max(dp[n][0],dp[n][1]);
20     return 0;
21 }

时间: 2024-10-07 01:35:50

动态规划——子序列的相关文章

动态规划(4)——最长上升子序列(作业题NYOJ201)

作业题 描述 小白同学这学期有一门课程叫做<数值计算方法>,这是一门有效使用数字计算机求数学问题近似解的方法与过程,以及由相关理论构成的学科-- 今天他们的Teacher S,给他们出了一道作业题.Teacher S给了他们很多的点,让他们利用拉格朗日插值公式,计算出某严格单调函数的曲线.现在小白抄下了这些点,但是问题出现了,由于我们的小白同学上课时走了一下神,他多抄下来很多点,也就是说这些点整体连线不一定还是严格递增或递减的了.这可怎么处理呢.为此我们的小白同学制定了以下的取点规则: 1.取

HDU 1003 Max Sum【动态规划求最大子序列和详解 】

Max Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 250714    Accepted Submission(s): 59365 Problem Description Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max su

动态规划:最大连续子序列和

问题:给出一个数组,求其连续子序列的最大和 package 动态规划; /** * 给出一个数组,求其连续子数组的最大和 * @author Administrator * */ public class MaxSum { public static void main(String[] args) { int[] arr = new int[]{-3,1,-3,4,-1,2,1}; int max=arr[0]; int current=arr[0]; for(int i=1;i<arr.le

动态规划-最长公共子序列

(1).问题描述:给出2个序列,x是从1到m,y是从1到n,找出x和y的最长公共子序列? x:A B C B D A B y:B D C A B A 则:最长公共子序列长度为4,BDAB BCAB BCBA均为LCS(最长公共子序列): 模型实现图: (2).问题解决 代码实现了最长公共子序列的长度 #include<stdio.h> #define N    10 int LCS(int *a, int count1, int *b, int count2); int LCS(int *a,

动态规划 - 最长公共子序列(LCS)

最长公共子序列也是动态规划中的一个经典问题. 有两个字符串 S1 和 S2,求一个最长公共子串,即求字符串 S3,它同时为 S1 和 S2 的子串,且要求它的长度最长,并确定这个长度.这个问题被我们称为 最长公共子序列问题. 与求最长递增子序列一样,我们首先将原问题分割成一些子问题,我们用 dp[i][j]表示 S1 中前 i 个字符与 S2 中前 j 个字符分别组成的两个前缀字符串的最 长公共子串长度. 显然的,当 i. j 较小时我们可以直接得出答案,如 dp[0][j]必 等于 0.那么,

动态规划之最长公共子序列(LCS)

tips : 本文内容是参考了很多著名博客和自己的思考得出的,如有不当欢迎拍砖. 先简单说一下动态规划 通俗地说:动态规划就是将一个可以划分为子问题的问题进行递归求解,不过动态规划将大量的中间结果保存起来, 不管它们是否会用得到,从而在后面的递归求解过程中可以快速求解.由此可以看得出来动态规划是一个以牺牲空间 为代价换取时间的算法. 对于最长公共子序列的题目不用多说,现在来分析一下LCS的动态规划解决思路: 一.首先先观察问题是否符合动态规划最明显的两个特征:最优子结构和重叠子问题 方便起见,以

动态规划专题(一) HDU1087 最长公共子序列

Super Jumping! Jumping! Jumping! 首先对于动态规划问题要找出其子问题,如果找的子问题是前n个序列的最长上升子序列,但这样的子问题不好,因为它不具备无后效性,因为它的第n+1的数会影响前n个序列的长度,换句话说,如果第n+1个数加上去不一定使得和前n个数加起来就是最长子序列,具体例子很多比如5,6,1,2 第5个数是3,那么最长序列5,6加3不会比1,2加3长. 比较好的子问题是“求以第K个为终点的最长上升子序列”,其实这个子问题的好处在于它限定了一点,终点为第k个

动态规划---最长上升子序列问题(O(nlogn),O(n^2))

LIS(Longest Increasing Subsequence)最长上升子序列 或者 最长不下降子序列.很基础的题目,有两种算法,复杂度分别为O(n*logn)和O(n^2) . ********************************************************************************* 先回顾经典的O(n^2)的动态规划算法: 设a[t]表示序列中的第t个数,dp[t]表示从1到t这一段中以t结尾的最长上升子序列的长度,初始时设dp[

算法——动态规划篇——最长公共子序列

问题描述      最长公共子序列,英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列.       解决最长公共子序列,一种常用的办法,就是穷举法,组合出所有的情况,但是这样对于长序列的情况来说,是非常不实际.. 假设现在有两个序列,x[]={'A','B','C','B','D','A','B'};y[]={'B','D','C','A'