首页 > 代码库 > POJ 1631 Bridging signals

POJ 1631 Bridging signals

题意:给出许多连线,要你删除一些使得剩下的连线最多且不想交,抽象出来就是最长上升序列问题(LIS)

LIS有两种经典解法,一种是DPO(N^2)的时间复杂度,还有一种二分O(NlogN)的时间复杂度。

第一种方法:

推荐题目PKOJ2533 ——Longest Ordered Subsequence 裸LIS

#include <iostream>
#include<stdio.h>
#include<string>
#include<cstring>
#include<cmath>
#define N 2222//最长上升子序列,n^2算法
using namespace std;
int dp[N];
int a[N];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        memset(dp,0,sizeof dp);
        for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
        dp[1]=1;int ans=1;
        for(int i=2;i<=n;i++)
        {
            int m=0;
            for(int j=1;j<i;j++)
            {
                if(dp[j]>m&&a[i]>a[j])
                   m=dp[j];
            }
            dp[i]=m+1;
            if(ans<dp[i])
            ans=dp[i];
        }
        printf("%d\n",ans);
    }
    return 0;
}

第二种方法:

POJ1631,给的数据40000,直接做的话会超时,所以要用二分来做

http://www.docin.com/p-540470161.html  豆丁上把这种方法讲解的很好的一个PPT,看了就懂

#include <iostream>
#include<stdio.h>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 45000
using namespace std;
int a[N];
int ans[N];//注意,ans数组储存的不是LIS,而是对应长度LIS的最小末尾
int len;
int binary_search(int i)
{
    int le,ri,mid;
    le=0;ri=len;
    while(le<ri)
    {
        mid=(ri+le)/2;
        if(ans[mid]>=a[i]) ri=mid;
        else
        le=mid+1;
    }
    return le;
}
int main()
{
    int n;
    int p;
    while(~scanf("%d",&n))
    {
        while(n--)
        {
            scanf("%d",&p);
            for(int i=1;i<=p;i++)
            scanf("%d",&a[i]);
            ans[1]=a[1];
             len=1;
            for(int i=1;i<=p;i++)
            {
                if(ans[len]<a[i])
                ans[++len]=a[i];
                else
                {
                    int pos=binary_search(i);
                    ans[pos]=a[i];
                }
            }
            printf("%d\n",len);
        }
    }
    return 0;
}

有关的题目推荐:POJ 1887  POJ 1609