LIS学习笔记(两种算法)

2017-09-02 10:34:21

writer:pprp

最长上升子序列,具体分析看代码:O(n^2)的做法,dp的思想

代码如下:

/*
@theme:LIS最长上升子序列
@writer:pprp
@begin:10:00
@end:10:15
@declare复杂度为O(n^2)
@error:dp[i] = MAX(dp[j]+1,dp[i]),dp[i] = 1初始化为1
@date:2017/9/2
*/

#include <bits/stdc++.h>

using namespace std;

/*
未优化的最长上升子序列
f(i)代表从头到i的位置最长上升子序列的长度
if( i < n && arr[i] < arr[n] )
    f(n) = max(f(i))+ 1;
dp[i]是如果取到arr[i]的时候的最长上升子序列
*/

int dp[10010],arr[10010];

int MAX(int a, int b)
{
    return a > b ? a : b;
}

int main()
{
    int N;
    while(cin >> N && N)
    {
        int max = 0;
        for(int i = 0 ; i < N ;i++)
        {
            dp[i] = 1;
            cin >> arr[i];
            for(int j = 0 ;j < i ; j++)
            {
                if(arr[j] < arr[i])
                    dp[i] = MAX(dp[j] + 1, dp[i]);
            }
            max = MAX(max,dp[i]);
        }
        cout << max << endl;
    }
    return 0;
}

2、采用了优化,记录了可能被选中的点,将其记录在tmp数组中,再从从其中进行查找

/*
@theme:tmp最长上升子序列
@writer:pprp
@begin:10:00
@end:14:32
@declare复杂度为O(n^2)
@error:dp[i] = MAX(dp[j]+1,dp[i]),dp[i] = 1初始化为1
@date:2017/9/2
*/

#include <bits/stdc++.h>

using namespace std;

int arr[10010],tmp[10010];
int len;

/*
状态定义:用到tmp数组
tmp[i]:代表的是对于所有长度为i的LIS,他的结果最小有可能是多少,
       如果越小那就越容易被取到
tmp中的元素是严格递增的
状态转移:
        if( dp[j] = i )
            tmp[i] = min(arr[j])
结果查找--用二分的方法去找
if(tmp[i] < arr[n] && tmp[i+1] >= arr[n] )
    f[n] = i+1 .... i 代表的是长度

*/

//二分查找,在tmp中进行二分查找arr[i]
//对tmp数组进行更新
void bisearch(int x)
{
    int left=1,mid,right=len;
    while(left<=right)
    {
        mid=(left+right)>>1;
        if(tmp[mid]<x)
            left=mid+1;
        else
            right=mid-1;
    }
    tmp[left]=x;
}

int main()
{
    int N;
    while(cin >> N && N)
    {
        len=1;
        cin >> arr[0];
        tmp[len]=arr[0];

        for(int i=1; i<N; i++)
        {
            scanf("%d",&arr[i]);

            if(arr[i] > tmp[len])//如果当前i指向的arr的值大于tmp当前的值
            {
                len++;
                tmp[len]=arr[i];
            }//向tmp数组中加入arr的值
            else
                bisearch(arr[i]);//在tmp中进行查找找到的就将其更新
            //如果用lower_bound的话就这样:
            //*lower_bound(tmp,tmp+len,arr[i]) = arr[i];
        }
        printf("%d\n",len);
    }
    return 0;
}
时间: 2025-01-17 01:41:16

LIS学习笔记(两种算法)的相关文章

[学习笔记]数据结构与算法

1.排序简单排序:?冒泡排序:将n个数从上往下排列,从第0个数开始依次对前n个.前n-1个.前n-2个数进行比较,保持小数在前大数在后,不符合就交换.在这个过程中,最后一个数始终是最大数.?选择排序:对所有n个.后n-1个.后n-2个依次比较,用一个变量存最小数,一趟比较完成之后,将最小数与所比较数据的第一个数进行交换.在这个过程中,第一个数始终是最小数.?插入排序:从第1个数开始向前扫描比较,小则插入.对于未排序数据,在已排序序列中向前扫描,并找到相应的位置插入.在这个过程中,整个序列局部有序

重拾算法(5)——最小生成树的两种算法及其对比测试

重拾算法(5)——最小生成树的两种算法及其对比测试 什么是最小生成树 求解最小生成树(Minimum Cost Spanning Tree,以下简写做MST)是图相关的算法中常见的一个,用于解决类似如下的问题: 假设要在N个城市之间建立通信联络网,那么连通N个城市只需N-1条线路.这时自然会考虑这样一个问题:如何在最节省经费的前提下建立这个通信网. 在任意两个城市间都可以设置一条线路,相应地都要付出一定的经济代价.N个城市之间最多可能设置N(N-1)/2条线路,那么如何在这些线路中选择N-1条,

hdu 1162 Eddy&#39;s picture 最小生成树入门题 Prim+Kruskal两种算法AC

Eddy's picture Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7428    Accepted Submission(s): 3770 Problem Description Eddy begins to like painting pictures recently ,he is sure of himself to

uboot学习之二----主Makefile学习之四----两种编译方法:原地编译和单独输出文件夹编译

第57-123行: 57 # 58 # U-boot build supports producing a object files to the separate external 59 # directory. Two use cases are supported: 60 # 61 # 1) Add O= to the make command line 62 # 'make O=/tmp/build all' 63 # 64 # 2) Set environement variable

次小生成树的两种算法

一."换边"算法 用Kruskal求最小生成树,标记用过的边.求次小生成树时,依次枚举用过的边,将其去除后再求最小生成树,得出所有情况下的最小的生成树就是次小的生成树.可以证明:最小生成树与次小生成树之间仅有一条边不同. 这样相当于运行m次Kruskal算法. 复杂度O(m^2) 示例代码: int Kruskal_MinTree() { int u,v; init(); int i,flag,cnt; minedge = 0; flag = cnt = 0; int tmp = 0;

最小生成树的两种算法:Prim和Kruskal算法

越来越明白了一个道理:你写不出代码的原因只有一个,那就是你没有彻底理解这个算法的思想!! 以前写过最小生成树,但是,水了几道题后,过了一段时间,就会忘却,一点也写不出来了.也许原因只有一个,那就是我没有彻底理解这两种算法. 主题: 其实,求最小生成树有两个要点,一个是权值最小,还有一个就是这个图必须是树.而Prim和Kruskal的不同之处在于两者选择的变量不同,Prim选择的是始终保持权值最小,然后逐个加点构建一棵树.而Kruskal则是始终保证是一棵树(虽然构建过程中不一定是真正的树,但并查

PHP实现指定时间的n月之前的这一天的两种算法

/** *根据$endtime,返回指定$monthes月之前的日 */ function severalMonthAgo($endtime,$monthes){ if (!$endtime) { return false; } if (!is_int($monthes) || $monthes <=0) { return false; } $m = date("m",$endtime); $y = date("Y",$endtime); $d = date(

安卓权威编程指南 - 第五章学习笔记(两个Activity)

学习安卓编程权威指南第五章的时候自己写了个简单的Demo来加深理解两个Activity互相传递数据的问题,然后将自己的学习笔记贴上来,如有错误还请指正. IntentActivityDemo学习笔记 题目:ActivityA登录界面(用户名.密码.登陆按钮),ActivityB(Edit,返回按键:SubmitButton).A界面输入用户名和密码传到B中,B验证用户输入的用户名和密码,如果错误就返回A,并用Toast 显示用户名和密码错误:如果正确,就在第二个 activity中显示一个Edi

STL学习笔记(变动性算法)

本节描述的算法会变动区间内的元素内容.有两种方法可以变动元素内容: 1.运用迭代器遍历序列的过程中,直接加以变动 2.将元素从源区间赋值到目标区间的过程中加以变动 复制(copy)元素 OutputIterator copy(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg) BiderectionalIterator copy_backward(BidirectionalIterator sourc

【转】jmeter学习笔记——一种简单的数据库性能测试方法

前提条件:一个数据库:test   数据库下面有一张表:user   表中有两个字段:username.passworld . 要求:往数据库内大批量插入数据,1000/s 其实和之前的方法一样,为了简单,我还是把截图贴出来吧. 1.创建一个测试计划,将我们所使用的数据库驱动包导入. 2.添加一个线程组,并设置我们的虚拟用户数.启动时间.和循环次数 3.创建一个线程,并在线程下面,创建一个JDBC Connection Configuration ,设置相关信息. 4.创建一个JDBC Requ