HDU 4512——吉哥系列故事——完美队形I——————【LCIS应用】
吉哥系列故事——完美队形I
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 2707 Accepted Submission(s): 886
有一天,有n个人按顺序站在他的面前,他们的身高分别是h[1], h[2] ... h[n],吉哥希望从中挑出一些人,让这些人形成一个新的队形,新的队形若满足以下三点要求,则称之为完美队形:
1、挑出的人保持他们在原队形的相对顺序不变;
2、左右对称,假设有m个人形成新的队形,则第1个人和第m个人身高相同,第2个人和第m-1个人身高相同,依此类推,当然,如果m是奇数,中间那个人可以任意;
3、从左到中间那个人,身高需保证递增,如果用H表示新队形的高度,则H[1] < H[2] < H[3] .... < H[mid]。
现在吉哥想知道:最多能选出多少人组成完美队形?
每组数据先输入原先队形的人数n(1<=n <= 200),接下来一行输入n个整数,表示按顺序从左到右原先队形位置站的人的身高(50 <= h <= 250,不排除特别矮小和高大的)。
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn = 550;
int dp[maxn][maxn];
int a[maxn], b[maxn];
int main(){
int T, n, m;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i = 1; i <= n; i++){
scanf("%d",&a[i]);
}
m = n;
for(int i = 1; i <= m; i++){
b[i] = a[m-i+1];
}
int ans = 0;
for(int i = 1; i <= n; i++){
int Max = 0;
for(int j = 1; j <= n-i+1; j++){
dp[i][j] = dp[i-1][j];
if(a[i] > b[j] && dp[i-1][j] > Max){
Max = dp[i-1][j];
}
if(a[i] == b[j]){
dp[i][j] = Max + 1;
}
if(j == n-i+1){
ans = max(ans,dp[i][j]*2-1);
}else{
ans = max(ans,dp[i][j]*2);
}
}
}
printf("%d\n",ans);
// for(int i = 1; i <= n; i ++){
// for(int j = 1; j <= m; j ++){
// printf("%d ",dp[i][j]);
// }puts("");
// }puts("");
}
return 0;
}
/*
55
4
3 4 1 3 4
3 2 1 3 4
3 2 2 3
*/
附:最长公共上升子序列算法
最长公共上升子序列(LCIS)的O(n^2)算法
预备知识:动态规划的基本思想,LCS,LIS。
问题:字符串a,字符串b,求a和b的LCIS(最长公共上升子序列)。
首先我们可以看到,这个问题具有相当多的重叠子问题。于是我们想到用DP搞。DP的首要任务是什么?定义状态。
1定义状态F[i][j]表示以a串的前i个字符b串的前j个字符且以b[j]为结尾构成的LCIS的长度。
为什么是这个而不是其他的状态定义?最重要的原因是我只会这个,还有一个原因是我知道这个定义能搞到平方的算法。而我这只会这个的原因是,这个状态定义实在是太好用了。这一点我后面再说。
我们来考察一下这个这个状态。思考这个状态能转移到哪些状态似乎有些棘手,如果把思路逆转一下,考察这个状态的最优值依赖于哪些状态,就容易许多了。这个状态依赖于哪些状态呢?
首先,在a[i]!=b[j]的时候有F[i][j]=F[i-1][j]。为什么呢?因为F[i][j]是以b[j]为结尾的LCIS,如果F[i][j]>0那么就说明a[1]..a[i]中必然有一个字符a[k]等于b[j](如果F[i][j]等于0呢?那赋值与否都没有什么影响了)。因为a[k]!=a[i],那么a[i]对F[i][j]没有贡献,于是我们不考虑它照样能得出F[i][j]的最优值。所以在a[i]!=b[j]的情况下必然有F[i][j]=F[i-1][j]。这一点参考LCS的处理方法。
那如果a[i]==b[j]呢?首先,这个等于起码保证了长度为1的LCIS。然后我们还需要去找一个最长的且能让b[j]接在其末尾的LCIS。之前最长的LCIS在哪呢?首先我们要去找的F数组的第一维必然是i-1。因为i已经拿去和b[j]配对去了,不能用了。并且也不能是i-2,因为i-1必然比i-2更优。第二维呢?那就需要枚举b[1]..b[j-1]了,因为你不知道这里面哪个最长且哪个小于b[j]。这里还有一个问题,可不可能不配对呢?也就是在a[i]==b[j]的情况下,需不需要考虑F[i][j]=F[i-1][j]的决策呢?答案是不需要。因为如果b[j]不和a[i]配对,那就是和之前的a[1]..a[j-1]配对(假设F[i-1][j]>0,等于0不考虑),这样必然没有和a[i]配对优越。(为什么必然呢?因为b[j]和a[i]配对之后的转移是max(F[i-1][k])+1,而和之前的i`配对则是max(F[i`-1][k])+1。显然有F[i][j]>F[i`][j],i`>i)
于是我们得出了状态转移方程:
a[i]!=b[j]: F[i][j]=F[i-1][j]
a[i]==b[j]: F[i][j]=max(F[i-1][k])+1 1<=k<=j-1&&b[j]>b[k]
不难看到,这是一个时间复杂度为O(n^3)的DP,离平方还有一段距离。
但是,这个算法最关键的是,如果按照一个合理的递推顺序,max(F[i-1][k])的值我们可以在之前访问F[i][k]的时候通过维护更新一个max变量得到。怎么得到呢?首先递推的顺序必须是状态的第一维在外层循环,第二维在内层循环。也就是算好了F[1][len(b)]再去算F[2][1]。
如果按照这个递推顺序我们可以在每次外层循环的开始加上令一个max变量为0,然后开始内层循环。当a[i]>b[j]的时候令max=F[i-1][j]。如果循环到了a[i]==b[j]的时候,则令F[i][j]=max+1。
最后答案是F[len(a)][1]..F[len(a)][len(b)]的最大值。
HDU 4512——吉哥系列故事——完美队形I——————【LCIS应用】的更多相关文章
- HDU 4512 吉哥系列故事——完美队形(LCIS)
Problem Description 吉哥这几天对队形比较感兴趣. 有一天,有n个人按顺序站在他的面前,他们的身高分别是h[1], h[2] ... h[n],吉哥希望从中挑出一些人,让这些人形成一 ...
- hdu 4512 吉哥系列故事——完美队形I LCIS
题目链接 给一个数列, 在里面选出一些数组成一个对称的数列, 数的顺序不能打乱. 使得左半边是一个严格递增的数列, 右边递减, 并且a[i] = a[n-i+1]. 就是一个对称的LCIS.. #in ...
- hdu 4512 吉哥系列故事——完美队形I【LCIS经典应用】
链接: http://acm.hdu.edu.cn/showproblem.php?pid=4512 http://acm.hust.edu.cn/vjudge/contest/view.action ...
- hdu 4512 吉哥系列故事——完美队形I_LCIS
题目链接 题意: 假设有n个人按顺序站在他的面前,他们的身高分别是h[1], h[2] ... h[n],吉哥希望从中挑出一些人,让这些人形成一个新的队形,新的队形若满足以下三点要 求,则就是新 ...
- hdu 4512 吉哥系列故事——完美队形I(最长公共上升自序加强版)
首先要去学习最长公共上升子序列LCIS.然后是对n*n效率的算法进行优化,这里要注意的是能够求出来的序列中间能够有一个最高的.刚開始将输入的数组进行逆置,写下来发现这可能存在问题. 只是详细是什么也没 ...
- LCIS HDOJ 4512 吉哥系列故事——完美队形I
题目传送门 题意:中文题面 分析:LCIS应用:设置b[]为a[]的反转,然后LCIS,若相等的是自己本身,则+1, 否则+2 代码: #include <cstdio> #include ...
- HDU 4513 吉哥系列故事――完美队形II(Manacher)
题目链接:cid=70325#problem/V">[kuangbin带你飞]专题十六 KMP & 扩展KMP & Manacher V - 吉哥系列故事――完美队形I ...
- HDU 4513 吉哥系列故事――完美队形II
http://acm.hdu.edu.cn/showproblem.php?pid=4513 吉哥系列故事——完美队形II Time Limit: 3000/1000 MS (Java/Others) ...
- HDU 4513 吉哥系列故事——完美队形II manacher
吉哥系列故事——完美队形II Problem Description 吉哥又想出了一个新的完美队形游戏! 假设有n个人按顺序站在他的面前,他们的身高分别是h[1], h[2] ... h[n],吉哥希 ...
随机推荐
- inline 内联函数
1.目的: 引入内联函数的目的是为了解决程序中函数调用的效率问题. 函数的引入可以减少程序的目标代码,实现程序代码和数据的共享.但是,函数调用也会带来降低效率的问题,因为调用函数实际上将程序执行顺序转 ...
- eval实例
.... var sel_MedicineType = 'sel_MedicineType' + lastIndex; eval(sel_MedicineType + "= new C_Se ...
- Binder学习笔记(八)—— 客户端如何组织Test()请求 ?
还从客户端代码看起TestClient.cpp:14 int main() { sp < IServiceManager > sm = defaultServiceManager(); / ...
- VS2015无法创建C++工程解决方法!!
VS2015默认安装时候没有安装C++,如果安装C++没有选择全部C++项目,则无法创建C++工程,在控制面板里的删除程序中,选择VS2015,随后选择修改,把C++项目都选择上就可以了,这样安装完毕 ...
- 多层mvc,thikphp进阶
程序员,是一种生活态度. 我尽忠恪守,我努力进取,热衷于解决问题,希望得到同样的回报. 我遇到问题,将所有的力量用在解决问题,而不是抱怨,推卸责任上. ------------------------ ...
- mybatis、Spring整合(eclipse)以及事务管理
1.项目目录 2.jar包 dbcp:连接池 pool:连接池 logging:日志 log4j:日志 mybatis-spring:用于SqlSession等相关操作 spring相关包 mybat ...
- web安全-传输安全
web安全-传输安全 anyproxy 代理服务器在之间可以看到 1.HTTP传输窃听 浏览器-代理服务器-链路-服务器 传输链路窃听篡改 2.HTTP窃听 >* 窃听用户密码 >* 窃听 ...
- left jion on和where条件的区别
1.on是在生成临时表时()起作用,而且不管on中的条件是否为真,都会返回(left join)左边所有的数据,如果不匹配也是返回空. 2.where 是在生成了临时表后,再对表进行过滤 个人理解:先 ...
- luogu4151 最大XOR和路径
然后呢这道题其实很简单 我们先考虑一种简单的情况,从1直接走到n(不管怎么走的,反正就是走) 然后就能找到一个路径了 这个走的过程用各种zmj算法都能过 然后呢我们发现如果直接走基本不会得到最优解,考 ...
- <aop:aspectj-autoproxy proxy-target-class="false"/>导致出现404状态码
今天干活的时候,由于是一个web应用,想在每次发送请求和返回响应的时候记录日志,也就是代理Controller,想起了之前的spring AOP,于是按照之前的配置配置好了,可是发现每次前端发送请求都 ...