HDU 1025 Constructing Roads In JGShining's Kingdom (LIS 最长递增子序列)

【题目链接】:click here~~

【题意】:河岸两旁有n个村庄,他们之间要互相修路,并且同一边的不互相修,在保证不交叉的情况下,最大限度的路的是多少。

【思路】转化题意后,发现是求LIS,入门题训练

LIS详细分析:LIS问题

代码:

/*  
* Problem: HDU No.1025
* Running time: 374MS  
* Complier: G++  
* Author: javaherongwei 
* Create Time:  8:47 2015/9/28 星期一
*LIS(最长递增子序列)
*/  
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N=500000+10;
int dp[N];
int B[N],C[N],D[N];
int len;
int LIS(int *a,int n);///计算最长递增子序列的长度,计算B数组的元素,arr[]循环完一遍后,B的长度len即为所求
int LISsearch(int *b,int len,int p);///二分查找需要插入的位置
int LIS(int *a,int n)
{
    len=1;
    B[0]=a[0];
    D[0]=1;///表示已i结尾的LIS
    int pos=0;
    for(int i=1; i<n; ++i)
    {
        if(a[i]>B[len-1])///如果大于B中最大的元素,则直接插入到B数组末尾
        {
            B[len]=a[i];
            ++len;
        }
        else
        {
            pos=LISsearch(B,len,a[i]);///二分查找需要插入的位置
            B[pos]=a[i];
        }
        D[i]=len;
    }
    return len;
}
int LISsearch(int *b,int len,int p)
{
    int left=0,right=len-1;
    int mid;
    while(left<=right)
    {
        mid=(left+right)>>1;
        if(b[mid]>p) right=mid-1;
        else if(b[mid]<p) left=mid+1;
        else return mid; ///找到了该元素,则直接返回
    }
    return left;
}
inline LL read()
{
    int  c=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
    return c*f;
}
int main()
{
     int t,tot=1;
     while(~scanf("%d",&t))
     {
         for(int i=0; i<t; ++i)
         {
             int a,b;
             a=read();b=read();
             dp[a-1]=b-1;
         }
         int ans=LIS(dp,t);
         printf("Case %d:\n",tot++);
         if(ans==1) {puts("My king, at most 1 road can be built.");puts("");}
        else { printf("My king, at most %d roads can be built.\n",ans);puts("");}
     } return 0;
}


你可能感兴趣的:(HDU,LIS,最长递增子序列)