zoukankan      html  css  js  c++  java
  • HDU_1025 Constructing Roads In JGShining's Kingdom

           借杭电这道题总结一下最长上升子序列(LIS)问题,最长上升子序列有o(n^2)和o(nlogn)两种算法(Matrix67那还有一种o(nm)的算法,不过没看懂)。

      o(n^2)算法不用多说,就是依次遍历整个序列,每一次求出从第一个数到当前这个数的最长上升子序列,直至遍历到最后一个数字为止,然后再取dp数组里最大的那个即为整个序列的最长上升子序列。我们用dp[i]来存放序列1-i的最长上升子序列的长度,那么dp[i]=max(dp[j])+1,(j∈[1, i-1]); 显然dp[1]=1,我们从i=2开始遍历后面的元素即可。

           LIS函数代码如下:

    // Author: Tanky Woo
    // Blog: www.WuTianQi.com
    int dp[1000];
    int LIS(int arr[1000], int n)
    {
    for(int i=1; i<=n; ++i)
    dp[i]
    = 0;
    int ans;
    dp[
    1] = 1;
    for(int i=2; i<=n; ++i)
    {
    ans
    = dp[i];
    for(int j=1; j<i; ++j)
    {
    if(arr[i]>arr[j] && dp[j]>ans)
    ans
    = dp[j];
    }
    dp[i]
    = ans+1;
    }
    ans
    = 0;
    for(int i=1; i<=n; ++i)
    {
    if(dp[i] > ans)
    ans
    = dp[i];
    }
    return ans;
    }

           另为一种o(nlogn)算法,这种算法的操作如下:

      开一个栈,每次取栈顶元素top和读到的元素temp做比较,如果temp > top 则将temp入栈;如果temp < top则二分查找栈中的比temp大的第1个数,并用temp替换它。最长序列长度即为栈的大小top。

    这也是很好理解的,对于x和y,如果x < y且Stack[y] < Stack[x],用Stack[x]替换Stack[y],此时的最长序列长度没有改变但序列Q的''潜力''增大了。

    举例:原序列为1,5,8,3,6,7

    栈为1,5,8,此时读到3,用3替换5,得到1,3,8;再读6,用6替换8,得到1,3,6;再读7,得到最终栈为1,3,6,7。最长递增子序列为长度4。

      这道题显然是用第二种算法(1 <= N <= 50W),代码如下:

    #include <stdio.h>

    #define N 500005

    int num[N], dp[N];

    int find(int low, int high, int i) //二分法查找 确定num[i]的位置
    {
    while(low <= high)
    {
    int mid = (low+high)/2;
    if(i > dp[mid]) low = mid + 1;
    else high = mid - 1;
    }
    return low; //返回其位置
    }

    int main()
    {
    int n, a, b, i, len, Case = 0, low;
      //freopen(
    "data.in", "r", stdin);
    while(scanf("%d", &n) != EOF)
    {
    for(i = 0; i < n; i++)
    {
      scanf(
    "%d%d", &a,&b);
    num[a]
    = b;
    }
    dp[
    1] = num[1];
    len
    = 1;
    for(i = 2; i <= n; i++)
    {

    low
    = find(1, len, num[i]); //确定num[i]的位置,
    dp[low]
    = num[i]; //如果num[i]比dp[]里的所有元素都大,则将num[i]存入dp[],否则替换掉dp[]序列里第一个比num[i]小的数
    if(low > len) len++; //如果low>len说明将num[i]存入了dp[],所求LIS的长度加1;
    }
    if(len == 1) printf("Case %d:\nMy king, at most %d road can be built.\n\n", ++Case, len);
    else printf("Case %d:\nMy king, at most %d roads can be built.\n\n", ++Case, len);
    }
       
    return 0;
    }
  • 相关阅读:
    在前后端分离的SpringBoot项目中集成Shiro权限框架
    过账销售订单装箱单报错:用库存单位数量表示的实际剩余数量不能为零
    外部系统调用AX服务
    InventSum Closed and ClosedQty
    固定资产日志过账报错
    AX批处理相关
    AX2012打开报表报错
    有折扣的销售订单过账
    AX版本查询
    AX2012 SSRS Report 相关
  • 原文地址:https://www.cnblogs.com/vongang/p/2126582.html
Copyright © 2011-2022 走看看