最长上升子序列函数注解

来源:互联网 发布:知乎怎么邮箱注册 编辑:程序博客网 时间:2024/06/05 05:07

最长上升子序列函数注解

    前一段做ICPC初赛题,有一道题总WA不过。然后看了一位博主的博文,才知道可以用动态规划+二分查找AC。

    【问题描述】

    One day, Kaitou Kiddo had stolen a priceless diamond ring. But detective Conan blocked Kiddo's path to escape from the museum. But Kiddo didn't want to give it back. So, Kiddo asked Conan a question. If Conan could give a right answer, Kiddo would return the ring to the museum.Kiddo: "I have an arrayA and a number k, if you can choose exactly k elements from A and erase them, then the remaining array is in non-increasing order or non-decreasing order, we sayA is a magic array. Now I want you to tell me whether A is a magic array. " Conan: "emmmmm..." Now, Conan seems to be in trouble, can you help him?

    【输入要求】

     The first line contains an integer T indicating the total number of test cases. Each test case starts with two integersn and k in one line, then one line with n integers: A1,A2An.
    1T20
        1n10  5
        0kn
        1Ai10  5

    【输出要求】

     For each test case, please output "A is a magic array." if it is a magic array. Otherwise, output "A is not a magic array." (without quotes).

    【输入示例】

   

34 11 4 3 75 24 1 3 1 26 11 4 3 5 4 6
    【输出示例】

A is a magic array.A is a magic array.A is not a magic array.
    【题目链接】

    杭电oj6197

    【简要复述】

    找寻给定数组中的最长不减串和最长不增串,与n-k比较,决定你的输出。 

    【可以参考】

     另一位博主的博文


    【我的注解】

    
#include "stdafx.h"

#include"iostream"
using namespace std;

/*
template<class T>
int LIS(T a[], int n)
{
    //  在笛卡尔二维坐标系中 该问题每个数组值都能找到对应的唯一一个离散点
    int i, j;
    int ans = 1;
    int m = 0;
    int *dp = new int[n + 1];
    dp[1] = 1; // 最少可以取第一个点

    for (i = 2; i <= n; i++)
    {
        m = 0;  // 最遭期望 没有可以接上的
        for (j = 1; j<i; j++)
        {
            if ( dp[j] > m && a[j] <= a[i] )
                m = dp[j]; // 已扩展点中寻找:可行max解
        }
        dp[i] = m + 1;  // 加的这个1是指a[i]

        if (dp[i]>ans)
            ans = dp[i]; // 动归 的刷新: 又扩展了一个新点
    }

    return ans;
}

*/


template<class T>
int bsearch(T c[], int n, T a) // 二分查找 复杂度:lgn
{
    int l = 1, r = n;
    while (l <= r)
    {
        int mid = (l + r) / 2;
        if (a > c[mid] && a <= c[mid + 1])
            return mid + 1; // >&&<= 换为: >= && <
        else if (a < c[mid])  
            r = mid - 1;
        else l = mid + 1;
    }
    return 0;
}

template<class T>
int LIS(T a[], int n)
{
    int i, j, size = 1; // 最起码是1
    T *c = new T[n + 1];
    c[1] = a[1];

    // c 存的是最优已扩展数组. 最优:只增,最长,每一个数字尽可能小;
    for (i = 2; i <= n; ++i)
    {
        // 比第一个小  替换第一个  
        if (a[i] <= c[1]) j = 1;// <= 换为: <
        // 比最后一个大 接在最优解组末尾 长度加1  
        else if (a[i] >c[size])
            j = ++size;   // > 换为: >=
        else // 用二分法 找合适位置替换
            j = bsearch(c, size, a[i]);
        c[j] = a[i]; // 实施替换
    }
    return size;
}


int main()
{
    int T,a[1000],rem;
    cin >> T;
    for (int i = 1; i <= T; i++) {
        cin >> a[i];
    }
    rem=LIS(a, T);
    
    cout << " LIS's return number is: "<< rem << endl;


    return 0;
}

  // 此代码稍事修改可用来解决杭电oj6197.