[vijosP1303]导弹拦截(最长上升子序列转LCS)
描述
某国为了防御敌国的导弹袭击,研发出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试验阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
格式
输入格式
输入数据只有一行,该行包含若干个数据,之间用半角逗号隔开,表示导弹依次飞来的高度(导弹最多有 20 枚,其高度为不大于 30000 的正整数)。
输出格式
输出数据只有一行,该行包含两个数据,之间用半角逗号隔开。第一个数据表示这套系统最多能拦截的导弹数;第二个数据表示若要拦截所有导弹至少要再添加多少套这样的系统。
样例1
样例输入1
389,207,155,300,299,170,158,65
样例输出1
6,1
很明显这题首先需要求最长上升序列,这题有比较多的做法,我这里选用LCS(最长公共子序列)做法,但问题是最长公共子序列是求A={a1,a2,a3...an}与B={b1,b2,b3....bm}的最长公共子序列,这里只有一个序列串。
所以首先我们需要copy源串,然后对副本进行降序排序,得到一个序列,然后两个序列进行LCS就可以得出最长下降序列了。
然后回溯找出LCS中求出的串,对源串进行删除,最后递归执行直到源串为0就好了。
Java AC Code:
public class Main {
//最长下降序列长度
public static int m = 0;
//还需要多少飞弹
public static int need = 0;
public static void main( String[] args ) {
Scanner sc = new Scanner( System.in );
while( sc.hasNext() ) {
m=0;
need=0;
String str = sc.nextLine();
int[] nums = getSplits( str, "," );
List<Integer> list = new ArrayList<Integer>();
for( int i = 0; i < nums.length; i++ ) {
list.add( nums[ i ] );
}
LCS( nums,list );
System.out.println( m+","+(need-1) );
}
}
//进行LCS
public static void LCS( int[] nums, List<Integer> list ) {
int[] sortNums = new int[ nums.length ];
int[][] b = new int[ nums.length + 1 ][ nums.length + 1 ];
int n = nums.length;
for( int i = 0; i < n; i++ ) {
sortNums[ i ] = nums[ i ];
}
Arrays.sort( sortNums );
int[] descNums = new int[ n ];
for( int i = 0; i < n; i++ ) {
descNums[ i ] = sortNums[ n - i - 1 ];
}
int[][] lcs = new int[ n + 1 ][ n + 1 ];
for( int i = 1; i <= n; i++ ) {
for( int j = 1; j <= n; j++ ) {
if( nums[ i - 1 ] == descNums[ j - 1 ] ) {
lcs[ i ][ j ] = lcs[ i - 1 ][ j - 1 ] + 1;
b[ i ][ j ] = 0;
} else {
if( lcs[ i - 1 ][ j ] > lcs[ i ][ j - 1 ] ) {
lcs[ i ][ j ] = lcs[ i - 1 ][ j ];
b[ i ][ j ] = -1;
} else {
lcs[ i ][ j ] = lcs[ i ][ j - 1 ];
b[ i ][ j ] = 1;
}
}
}
}
//递归求need,并且判断获取最长的下降序列。
m = lcs[n][n] > m?lcs[n][n]:m;
while(list.size() !=0){
printLCS( b, nums, n, n, list );
int[] newNums = new int[list.size()];
for(int i=0;i<list.size();i++){
newNums[i] = list.get( i);
}
LCS(newNums,list);
need++;
}
}
//输入分片
public static int[] getSplits( String str, String pattern ) {
String[] splits = str.split( pattern );
int[] ret = new int[ splits.length ];
for( int i = 0; i < ret.length; i++ ) {
ret[ i ] = Integer.parseInt( String.valueOf( splits[ i ] ) );
}
return ret;
}
//回溯输出最长序列。
public static void printLCS( int[][] b, int[] nums, int i, int j,List<Integer> list) {
if( i == 0 || j == 0 )
return;
else if( b[ i ][ j ] == 0 ) {
printLCS( b, nums, i - 1, j - 1,list );
list.remove( new Integer(nums[i-1]) );
} else if( b[ i ][ j ] == -1 ) {
printLCS( b, nums, i - 1, j,list );
} else {
printLCS( b, nums, i, j - 1,list);
}
}
}
关于LCS算法的具体实现,自行百度啦,主要就是进行矩阵Dp,判断相等于不相等时候的选择大小。
[vijosP1303]导弹拦截(最长上升子序列转LCS)的更多相关文章
- 洛谷 - P1020 - 导弹拦截 - 最长上升子序列
https://www.luogu.org/problemnew/show/P1020 终于搞明白了.根据某定理,最少需要的防御系统的数量就是最长上升子序列的数量. 呵呵手写二分果然功能很多,想清楚自 ...
- 最长公共子序列问题 (LCS)
给定两个字符串S和T.求出这两个字符串最长的公共子序列的长度. 输入: n=4 m=4 s="abcd" t="becd" 输出: 3("bcd&qu ...
- 动态规划法(十)最长公共子序列(LCS)问题
问题介绍 给定一个序列\(X=<x_1,x_2,....,x_m>\),另一个序列\(Z=<z_1,z_2,....,z_k>\)满足如下条件时称为X的子序列:存在一个严格 ...
- 动态规划经典——最长公共子序列问题 (LCS)和最长公共子串问题
一.最长公共子序列问题(LCS问题) 给定两个字符串A和B,长度分别为m和n,要求找出它们最长的公共子序列,并返回其长度.例如: A = "HelloWorld" B = & ...
- 【Luogu P1439】最长公共子序列(LCS)
Luogu P1439 令f[i][j]表示a的前i个元素与b的前j个元素的最长公共子序列 可以得到状态转移方程: if (a[i]==b[j]) dp[i][j]=dp[i-1][j-1]+1; d ...
- 最长公共子序列(LCS)、最长递增子序列(LIS)、最长递增公共子序列(LICS)
最长公共子序列(LCS) [问题] 求两字符序列的最长公共字符子序列 问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字 ...
- 清橙 A1120 拦截导弹 -- 动态规划(最长上升子序列)
题目地址:http://oj.tsinsen.com/A1120 问题描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但 ...
- VijosP1303 导弹拦截
背景 实中编程者联盟为了培养技术精湛的后备人才,必须从基础题开始训练. 描述 某国为了防御敌国的导弹袭击,研发出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度, ...
- 【线型DP模板】最上上升子序列(LIS),最长公共子序列(LCS),最长公共上升子序列(LCIS)
BEGIN LIS: 一个数的序列bi,当b1 < b2 < … < bS的时候,我们称这个序列是上升的.对于给定的一个序列(a1, a2, …, aN),我们可以得到一些上升的子序 ...
随机推荐
- Postgresql standby(备机只读)环境搭建
下载PostgreSQL源码包,放在任意目录 设置/etc/sysctl.conf,增加以下内容 kernel.shmmni= 4096 kernel.sem =501000 6412800000 5 ...
- Prolog 外部不能有 DOCTYPE 声明。处理资源 'http://192.168.115.152:8082/api/EmpApi.aspx' 时出错。第 3 行,位置: 11
在Default.aspx代码中删除以下代码(其他窗口也是这样删除): <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitiona ...
- C# winform初学者实例
快递单打印通 下载地址: http://pan.baidu.com/s/1nue5ifn
- 开源第三方登录组件OAuthLogin2.0 支持QQ,阿里巴巴,淘宝,京东,蘑菇街,有赞等平台
Nuget地址:https://www.nuget.org/packages/OAuthLogin2.0/ 项目结构说明: AuthorizationProviders文件夹下主要存放内置的授权平台. ...
- css3模拟jq点击事件
还是这个梗,收好冷.今天是一个css3模拟jq点击事件,因为我发现,css3中没有类似于,js的点击事件,那么,可不可以仿照 jq的效果,类似的做一个呢?主要用到,input里面的radio 单选按钮 ...
- 从0到1学习node之简易的网络爬虫
本文地址: http://www.xiabingbao.com/node/2017/01/19/node-spider.html 我们这节的目标是学习完本节课程后,能进行网页简单的分析与抓取,对抓取到 ...
- 转:Oracle弃用sun.reflect.Reflection.getCallerClass
http://www.infoq.com/cn/news/2013/07/Oracle-Removes-getCallerClass 作为Java开发者,我们经常忽略@Deprecated注释,继续使 ...
- android Android性能优化之如何避免Overdraw
什么是Overdraw? Overdraw就是过度绘制 怎么来消灭overdraw呢?总的原则就是:尽量避免重叠不可见元素的绘制,基于这个原则,我们大概可以想出以下几招: 第一招:合理选择控件容器 ...
- matlab中运用项目思维分析问题并解决问题
我们将沿着以下几步思考:1.State the problem关于这个例子陈述问题很简单.我们想写一个判定二元一次方程的程序:是否有两个实根,重复实根,或者两个复数根2.Define the inpu ...
- python - bilibili(三)wireshark分析
当我们开始打开浏览器,并进入B站直播网页前,我们打开wireshark软件(软件的下载与安装请百度一下)开始截取当前数据. 然后输入直播间网址,enter进入就可以停止截取数据了,然后我们分析所截取的 ...