poj-1836-Alignment-dp-最长最短子序列问题

2023-10-16 21:08

本文主要是介绍poj-1836-Alignment-dp-最长最短子序列问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题意:

给你一排士兵,然后给你他们的身高,让你求最少剔除几个士兵之后,剩下的士兵的每一个士兵都能看见最左边的风景或者是最右边的风景。

做法:

按照题意就是求最少剔除几个士兵,才是得一排士兵的高度组成一个三角形。

求出最大上升子序列lens【i】,最大下降子序列lenx【i】。

如果以一个士兵i为三角形的头的话,那么这排士兵最多可以保留lens【i】+lenx【i】-1个人。

那么求出最大的赋为max,那么需要剔除的人数为n-max+1人。

还有一种特殊情况:

如果作为三角形头的士兵有登高的两个人的话,那么这两个人都可以保留,意思就是这个三角形上面的尖可以是平的,那么怎么消除这种特殊情况呢?

做法就是:如果这两个人是最后剩下的三角形的顶的话,那么这两个人的身高是一样的,这两个人的lens+lenx的值也是一样的,这样只要满足这两个条件,

就可以判定为这两个人是三角形的顶。然后那这两个人的lenx+lens的值加一即可。



#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
int main()
{int i,n,j;double a[1001];cin>>n;for(i=0;i<n;i++){cin>>a[i];}int lens[1001];memset(lens,0,sizeof(lens));lens[0]=1;for(i=0;i<n;i++){int max=1;for(j=0;j<i;j++){if(a[i]>a[j]&&lens[j]+1>max){max=lens[j]+1;}}if(lens[i]<max)lens[i]=max;}int lenx[1002];memset(lenx,0,sizeof(lenx));lenx[n]=1;for(i=n-1;i>=0;i--){int max=1;for(j=n-1;j>i;j--){if(a[i]>a[j]&&lenx[j]+1>max){max=lenx[j]+1;}}if(lenx[i]<max)lenx[i]=max;}for(i=0;i<n;i++){lens[i]=lens[i]+lenx[i];}int len[1001];for(i=0;i<n;i++)len[i]=lens[i];for(i=0;i<n;i++){int m=0;int mx=0;for(j=0;j<n;j++){if(a[i]==a[j]&&lens[i]==lens[j]){m++;}else{if(mx<m)mx=m;}}if(m)len[i]+=m-1;}for(i=0;i<n;i++)lens[i]=len[i];int max=0;for(i=0;i<n;i++){if(lens[i]>max)max=lens[i];}printf("%d\n",n-max+1);return 0;
}


这篇关于poj-1836-Alignment-dp-最长最短子序列问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/220778

相关文章

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

hdu4826(三维DP)

这是一个百度之星的资格赛第四题 题目链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1004&cid=500 题意:从左上角的点到右上角的点,每个点只能走一遍,走的方向有三个:向上,向下,向右,求最大值。 咋一看像搜索题,先暴搜,TLE,然后剪枝,还是TLE.然后我就改方法,用DP来做,这题和普通dp相比,多个个向上

hdu1011(背包树形DP)

没有完全理解这题, m个人,攻打一个map,map的入口是1,在攻打某个结点之前要先攻打其他一个结点 dp[i][j]表示m个人攻打以第i个结点为根节点的子树得到的最优解 状态转移dp[i][ j ] = max(dp[i][j], dp[i][k]+dp[t][j-k]),其中t是i结点的子节点 代码如下: #include<iostream>#include<algorithm

hdu4865(概率DP)

题意:已知前一天和今天的天气概率,某天的天气概率和叶子的潮湿程度的概率,n天叶子的湿度,求n天最有可能的天气情况。 思路:概率DP,dp[i][j]表示第i天天气为j的概率,状态转移如下:dp[i][j] = max(dp[i][j, dp[i-1][k]*table2[k][j]*table1[j][col] )  代码如下: #include <stdio.h>#include

poj3261(可重复k次的最长子串)

题意:可重复k次的最长子串 解题思路:求所有区间[x,x+k-1]中的最小值的最大值。求sa时间复杂度Nlog(N),求最值时间复杂度N*N,但实际复杂度很低。题目数据也比较水,不然估计过不了。 代码入下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring

usaco 1.1 Broken Necklace(DP)

直接上代码 接触的第一道dp ps.大概的思路就是 先从左往右用一个数组在每个点记下蓝或黑的个数 再从右到左算一遍 最后取出最大的即可 核心语句在于: 如果 str[i] = 'r'  ,   rl[i]=rl[i-1]+1, bl[i]=0 如果 str[i] = 'b' ,  bl[i]=bl[i-1]+1, rl[i]=0 如果 str[i] = 'w',  bl[i]=b

购买磨轮平衡机时应该注意什么问题和技巧

在购买磨轮平衡机时,您应该注意以下几个关键点: 平衡精度 平衡精度是衡量平衡机性能的核心指标,直接影响到不平衡量的检测与校准的准确性,从而决定磨轮的振动和噪声水平。高精度的平衡机能显著减少振动和噪声,提高磨削加工的精度。 转速范围 宽广的转速范围意味着平衡机能够处理更多种类的磨轮,适应不同的工作条件和规格要求。 振动监测能力 振动监测能力是评估平衡机性能的重要因素。通过传感器实时监

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s