hdu1025 dp(最长上升子序列LIS)
题意:有一些穷国和一些富国分别排在两条直线上,每个穷国和一个富国之间可以建道路,但是路不能交叉,给出每个穷国和富国的联系,求最多能建多少条路
我一开始在想有点像二分图匹配orz,很快就发现,当我把穷国按顺序排了之后,富国写在它旁边,能够连接的富国就成了一个上升子序列,那么问题来了!上升子序列最长有多长?
想到了这个之后,代码就码起来吧,最开始我的做法是最土的那种,用 dp[i] 表示以 i 结尾的最长上升子序列的长度,每次对于一个 i 遍历 i 前面的所有数 j ,取小于 i 的所有 j 的最大 dp[j] ,在这个基础上加一就是以 i 结尾的最长上升子序列的长度了。
于是,就这么水过了此文终结```怎么可能!显然我TLE了!我考虑了各种简化循环的姿势,比如把循环放进读取里面啊这类的```然后```我以不同的姿势连T了三次T得不要不要的。
看了题解```dp+二分优化```你们可懂我的心情如同万千草泥马奔过```我左思右想我的程序怎么加入二分法,可是明显并不能,仔细看题解之后才发现并不是我这么求的LIS。
这里的 dp 记录的是长度为 i 的上升子序列的最优结尾情况,也就是记录长度为 i 的上升子序列的结尾最短可以是多少。
模拟一下这个 dp 的方式:
例如我们现在有一个序列 10 1 3 2 4 7 9 5 6 8
首先起始是第一个数 10 ,那么我首先记录 dp[1]=10 ,这表示我当前状态下长度为 1 的子序列最小的结尾是 10 ,这个子序列就是 10;
接下来我遍历到第二个数 1 ,1 明显是小于 dp[1] 也就是 10 的,那么我就用 1 更新 dp[1] ,dp[1]=1 ,这表示遍历到第二个数 1 时,长度为 1 的子序列最小结尾是 1,这个子序列就是 1;
然后我遍历第三个数 3 ,3 大于 dp[1] 也就是 3 大于 1,那么我就记录 dp[2]=3 ,这表示此时长度为 2 的子序列最小结尾是 3,而这个子序列就是 1 3;
第四个数 2, 2 小于 dp[2] ,那我就在前面的值里找第一个比 2 大的值将它替代,dp[1]=1<2 ,dp[2]=3>2 ,于是我用 2 更新 dp[2]=2 ;表示此时长度为 2 的上升子序列最小结尾是 2 ,这个子序列就是 1 2;
第五个数 4 , 4 大于 dp[2] ,那么我就记录 dp[3]=4 ,表示长度 3 的子序列最小结尾是 4 ,这个子序列是 1 2 4;
第六个数 7 , 7 大于 dp[3] ,记录 dp[4]=7 ,代表子序列 1 2 4 7;
第七个数 9 , 9 大于 dp[4] ,记录 dp[5]=9 ,代表子序列 1 2 4 7 9;
第八个数 5 , 5 小于 dp[5] , 那么在 dp 数组中找第一个比 5 大的数优化它,寻找到了 dp[4]=7 ,那么就改为 dp[4]=5 ,代表此时长度为 4 的子序列最小结尾为 5 ,即子序列 1 2 4 5 ;
第九个数 6 , 6 小于 dp[5] ,那么在 dp 数组中找第一个比 6 大的数优化它,寻找到了 dp[5]=9 ,那么改为 dp[5]=6 ;代表此时长度为 5 的子序列最小结尾为 6 ,1 2 4 5 6;
最后一个数 8 , 8 大于 dp{5] ,那么直接记录 dp[6]=8 ,代表子序列 1 2 4 5 6 8;
这样整个最长上升子序列就出现了 1 2 4 5 6 8 ,长度为 6 ,在这种算法中,当数列非常长的时候,在前面所有的 dp 数组中寻找首个比当前数大的数的位置就非常耗时,因此即使仅仅 dp 是会 TLE 的,由于 dp 数组无论怎么更新都是保证上升的,因此我们就可以将寻找的工作加入二分查找的思想,这样就能保证数据大的情况下不会超时了。
恩```基本就是这样,但是我显然在 T 了三次之后又 WA 了几次,坑爹的事实粗线了,大概没有人会像我这么蠢得以为它给的时候穷国的顺序一定是从 1 开始一直上升的所以根本就不用读第一个数只要读它对应的富国就好了吧```我已经感受到了世界对我深深的恶意```代码里那绿绿的一段就是我当初觉得一定是按顺序的就可以把 dp 过程直接放入读数据循环来减少循环了```
#include<stdio.h>
#include<string.h>
int g[],dp[];
int main(){
int n;
int ti=;
while(scanf("%d",&n)!=EOF){
memset(g,,sizeof(g));
memset(dp,,sizeof(dp));
int ans=;
for(int p=;p<=n;p++){
int t,l;
scanf("%d%d",&t,&l);
g[t]=l;
}
dp[++ans]=g[];
for(int i=;i<=n;i++){
int low,high,mid;
low=;high=ans;
while(low<=high){
mid=(low+high)/;
if(dp[mid]<g[i])low=mid+;
else high=mid-;
}
dp[low]=g[i];
if(low>ans)ans++;
}
printf("Case %d:\n",++ti);
if(ans==) printf("My king, at most 1 road can be built.\n");
else printf("My king, at most %d roads can be built.\n",ans);
printf("\n");
}
return ;
}
hdu1025 dp(最长上升子序列LIS)的更多相关文章
- 动态规划(DP),最长递增子序列(LIS)
题目链接:http://poj.org/problem?id=2533 解题报告: 状态转移方程: dp[i]表示以a[i]为结尾的LIS长度 状态转移方程: dp[0]=1; dp[i]=max(d ...
- DP——最长上升子序列(LIS)
DP——最长上升子序列(LIS) 基本定义: 一个序列中最长的单调递增的子序列,字符子序列指的是字符串中不一定连续但先后顺序一致的n个字符,即可以去掉字符串中的部分字符,但不可改变其前后顺序. LIS ...
- 1. 线性DP 300. 最长上升子序列 (LIS)
最经典单串: 300. 最长上升子序列 (LIS) https://leetcode-cn.com/problems/longest-increasing-subsequence/submission ...
- 最长上升子序列LIS(51nod1134)
1134 最长递增子序列 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递 ...
- 【部分转载】:【lower_bound、upperbound讲解、二分查找、最长上升子序列(LIS)、最长下降子序列模版】
二分 lower_bound lower_bound()在一个区间内进行二分查找,返回第一个大于等于目标值的位置(地址) upper_bound upper_bound()与lower_bound() ...
- 最长回文子序列LCS,最长递增子序列LIS及相互联系
最长公共子序列LCS Lintcode 77. 最长公共子序列 LCS问题是求两个字符串的最长公共子序列 \[ dp[i][j] = \left\{\begin{matrix} & max(d ...
- 2.16 最长递增子序列 LIS
[本文链接] http://www.cnblogs.com/hellogiser/p/dp-of-LIS.html [分析] 思路一:设序列为A,对序列进行排序后得到B,那么A的最长递增子序列LIS就 ...
- hdu 1025 dp 最长上升子序列
//Accepted 4372 KB 140 ms //dp 最长上升子序列 nlogn #include <cstdio> #include <cstring> #inclu ...
- 题解 最长上升子序列 LIS
最长上升子序列 LIS Description 给出一个 1 ∼ n (n ≤ 10^5) 的排列 P 求其最长上升子序列长度 Input 第一行一个正整数n,表示序列中整数个数: 第二行是空格隔开的 ...
- 一个数组求其最长递增子序列(LIS)
一个数组求其最长递增子序列(LIS) 例如数组{3, 1, 4, 2, 3, 9, 4, 6}的LIS是{1, 2, 3, 4, 6},长度为5,假设数组长度为N,求数组的LIS的长度, 需要一个额外 ...
随机推荐
- powershell玩转litedb数据库
powershell可以玩nosql数据库吗?答案是肯定的.只要这个数据库兼容.net,就可以很容易地被powershell使用. 发文初衷:世界上几乎没有讲powershell调用nosql的帖子, ...
- idea使用generator自动生成model、mapper、mapper.xml(转)
原文链接:http://www.mamicode.com/info-detail-445217.html TEP 0.在Intellij IDEA创建maven项目(本过程比较简单,略) STEP 1 ...
- 2013年7月份第1周51Aspx源码发布详情
启睿网络信息服务器实例源码 2013-7-5 [ VS2005 ]功能介绍:睿网络信息服务器,QiRui Net Information Services简称QRNIS,该软件前身系KCIS.当前版 ...
- 2016 - 1- 21 - RunLoop使用(2016-1-24修改一次)&(2016 - 1 - 24 再次修改)
一:常驻线程 :当需要一个线程一直处理一些耗时操作时,可以让它拥有一个RunLoop.具体代码如下: 1.通过给RunloopMode里加源来保证RunLoop不直接退出. 这里有个很重要得知识 ...
- 解决:Android4.3锁屏界面Emergency calls only - China Unicom与EMERGENCY CALL语义重复
从图片中我们可以看到,这里在语义上有一定的重复,当然这是谷歌的原始设计.这个问题在博客上进行共享从表面上来看着实没有什么太大的意义,不过由于Android4.3在锁屏功能上比起老版本做了很大的改动,而 ...
- kali 2016的基础配置
1.Kali 2016的更新源 deb http://http.kali.org/kali kali-rolling main contrib non-free 2.安装虚拟机 apt-get upd ...
- PHP中的数组(二)常用数组处理函数
数组的相关处理函数 一.数组键/值操作有关的函数 1.array_values() 无论是关联的还是索引的返回的都是索引数组 <?php $lamp=array(&quo ...
- HDU 5009
http://acm.hdu.edu.cn/showproblem.php?pid=5009 题意:一个数列,每个点代表一种颜色,每次选一个区间覆盖,覆盖的代价是区间内颜色种类数的平方,直到覆盖整个数 ...
- M1: 创建UWP空项目
本小节介绍如何在Visual Studio中创建一个UWP项目,Visual Studio中提供了快速创建各种项目的类型模板.在Visual Studio 2015中,同样提供了UWP项目模板. 学完 ...
- magento产品成功添加到购物车后跳转到不同页面 添加 add to cart 按钮
1 添加产品到购物车成功后是跳转到购物车页面或不跳转.这个在后台可以设置 system -> configuration -> After Adding a Product Redirec ...