【动态规划+二分查找】POJ2533&POJ1631最长上升子序列(LIS)

POJ2533裸的LIS,时间复杂度为O(n^2)

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 const int MAXN=1000+5;
 5 int a[MAXN];
 6 int dp[MAXN];
 7 int n,ans;
 8
 9 int main()
10 {
11     scanf("%d",&n);
12     for (int i=0;i<n;i++)
13     {
14         scanf("%d",&a[i]);
15         dp[i]=1;
16     }
17     ans=-1;
18     for (int i=1;i<n;i++)
19     {
20         for (int j=0;j<i;j++)
21             if (a[j]<a[i] && dp[j]+1>dp[i])
22             {
23                 dp[i]=dp[j]+1;
24             }
25         if (dp[i]>ans)
26             {
27                 ans=dp[i];
28             }
29     }
30     cout<<ans<<endl;
31     return 0;
32 }

POJ1631

两条线路i与j不交叉的前提条件是a[i]<a[j],即上升子序列。用二分搜索+LIS,时间复杂度为O(n^2),具体解释详见《挑战程序设计竞赛2.3记录结果在利用的“动态规划”》P65

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 const int MAXN=40000+5;
 5 const int INF=1000000+5;
 6 int a[MAXN];
 7 int dp[MAXN];//dp[i]表示长度为i+1的上升子序列末位元素的最小值
 8 int n,m,ans,l,r;
 9
10 int search(int k)
11 {
12     int ul=l,ur=r;
13     while (ur-ul>1)
14     {
15         int mid=(ur+ul)/2;
16         if (dp[mid]>=k) ur=mid;
17             else ul=mid;
18     }
19     return ur;
20 }
21
22 int main()
23 {
24     scanf("%d",&m);
25     for (int kase=0;kase<m;kase++)
26     {
27         scanf("%d",&n);
28         for (int i=0;i<n;i++)
29         {
30             scanf("%d",&a[i]);
31             dp[i]=INF;
32         }
33         l=-1;
34         r=0;
35         for (int i=0;i<n;i++)
36         {
37             int pos=search(a[i]);
38             dp[pos]=a[i];
39             if (pos==r) r++;
40         }
41         cout<<r<<endl;
42     }
43     return 0;
44 }
时间: 2024-08-11 01:12:04

【动态规划+二分查找】POJ2533&POJ1631最长上升子序列(LIS)的相关文章

动态规划系列【2】最长递增子序列LIS

Given an unsorted array of integers, find the length of longest increasing subsequence. For example, Given [10, 9, 2, 5, 3, 7, 101, 18], The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that there may be more than

动态规划(DP),最长递增子序列(LIS)

题目链接:http://poj.org/problem?id=2533 解题报告: 状态转移方程: dp[i]表示以a[i]为结尾的LIS长度 状态转移方程: dp[0]=1; dp[i]=max(dp[k])+1,(k<i),(a[k]<a[i]) #include <stdio.h> #define MAX 1005 int a[MAX];///存数据 int dp[MAX];///dp[i]表示以a[i]为结尾的最长递增子序列(LIS)的长度 int main() { int

最长上升子序列LIS解法(n^n &amp;&amp; nlogn)

最长递增子序列问题 在一列数中寻找一些数满足 任意两个数a[i]和a[j] 若i<j 必有a[i]<a[j] 这样最长的子序列称为最长递增子序列LIS LIS问题有两种常见的解法 一种时间复杂度n^n 一种时间复杂度nlogn 下面我们先来说一下n^n的算法 设dp[i]表示以i结尾的最长上升子序列的长度 把问题分解 分解成序列中每一项最为终点的最大上升子序列 从第二项开始依次判断 最后找出最大的一项就是答案 则状态转移方程为 dp[i] = max{dp[j]+1}, 1<=j<

poj1836——dp,最长上升子序列(lis)

poj1836——dp,最长上升子序列(lis) Alignment Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 13767   Accepted: 4450 Description In the army, a platoon is composed by n soldiers. During the morning inspection, the soldiers are aligned in a straight

最长上升子序列LIS模板

1 ///最长上升子序列LIS模板 2 int BinSerch(int l,int r,int cut) 3 { 4 while (l<=r) 5 { 6 int m=(l+r)>>1; 7 if (cut>d[m]&&cut<=d[m+1]) return m; 8 if (cut>d[m]) l=m+1; 9 else r=m-1; 10 } 11 return 0; 12 } 13 14 int LIS(int n) 15 { 16 int le

动态规划(DP)之最长上升子序列

问题描述 一个数的序列ai ,当a1<a2<...<aS的时候,我们称这个序列是上升的.对于给定的一个序列(a1,a2,...,aN),我们可以得到一些上升的子序列(ai1,ai2,...,aik),这里1<=i1<i2<...<iK<=N.比如,对于序列(1, 7, 3, 5, 9, 4, 8) ,有它的一些上升子序列,如(1, 7), (3, 4, 8) 等等.这些子序列中最长的长度是4,比如子序列(1, 3, 5, 8).对于给定的序列,求出最长上升子

【算法导论学习-29】动态规划经典问题02:最长公共子序列问题(Longest common subsequence,LCS)

问题描述:序列X={x1,x2,-,xn},Y={y1,y2,-,yn},当Z={z1,z2-,zn}是X的严格递增下标顺序(可以不连续)的子集,也是Y的严格递增下标顺序(可以不连续)的子集,则Z是X和Y的公共子序列.例如X={A,B,C,B,D,A,B},Y={B,D,C,A,B,A},{B,C,A}.{B,C,B,A}.{B,D,A,B}都是X和Y的公共子序列.其中最长的公共子序列叫做Longest common subsequence,即经典的LCS. 具体点:char[]xArray和c

DP 动态规划 Problem B 1002 求最长上升子序列的长度

Problem B  ID:1002 简单题意:给出X和Z两个字符串,求最长上升子序列的长度. 解题思路形成过程:利用矩阵.X字符串中的各字符依次作为行标,Z字符串中的各字符依次作为列标. 从第一行第一列开始逐行遍历:如果当前位置对应的两个字符相同,则在这个位置记录"前一行前一列"的对应的数+1: 如果当前位置对应的两个字符不同,则在这个位置记录"此行前一列"和"此列前一行"对应的两个数的最大值. 遍历结束后,最后一行最后一列获得的数便是最长上升

动态规划|蒜头君跳木桩-最长下降子序列

蒜头君跳木桩 蒜头君面前有一排?nn?个木桩,木桩的高度分别是h_1,h_2,h_3\cdots h_nh1?,h2?,h3??hn?.蒜头第一步可以跳到任意一个木桩,接下来的每一步蒜头不能往回跳只能往前跳,并且跳下一个木桩的高度?不大于?当前木桩.蒜头君希望能踩到尽量多的木桩,请你帮蒜头计算,最多能踩到多少个木桩. 输入格式 第一行输入一个整数?nn?代表木桩个数.第二行输入?nn?个整数?h_1,h_2,h_3\cdots h_nh1?,h2?,h3??hn?,分别代表?nn?个木桩的高度.