poj 1887 Testing the CATCHER

12 篇文章 0 订阅

分类:dp-lis 难度1.5

 

题意:求最长递增子序列。

最长递增子序列LIS的三种解法:

1、转换为最长公共子序列LCS(先排序,找排序后和原序列的LCS)

2、DP解法(O(n^2)),f(i)是以L[i]为末元素最长递增子序列的长度,遍历前i-1个元素,找满足L[j]<L[i]的max(f(j)),f[i]=f[j]+1,最后遍历f[i]找最大值,即为LIS

#include<cstdio>
#include<cstring>

const int N = 10010;
int l[N],n,f[N];

int main()
{
	int cnt = 1;
	for(;scanf("%d",&l[0]) && l[0]>=0;cnt++)
	{
		int i,j;
		for(i=1;;i++)
		{
			scanf("%d",l+i);
			if(l[i]<0) break;
		}
		n=i;
		for(i=0;i<n;i++) f[i]=1;
		for(i=n-2;i>=0;i--)
			for(j=n-1;j>i;j--)
				if(l[j]<=l[i] && f[j]+1>f[i])
					f[i]=f[j]+1;
		int ans=0;
		for(i=0;i<n;i++)
			if(f[i]>ans) ans = f[i];
		printf("Test #%d:\n  maximum possible interceptions: %d\n\n",cnt,ans);
	}
} 

176k 63ms

3、优化DP解法(二分查找 O(nlogn)),B[f(j)]=L[j],每次在B[f(j)]中二分查找当前L[i]插入位置p,即满足B[p-1]<L[i],B[p]>L[i]的p(l[i]>B[当前max],则B[当前max+1]=l[i]),将B[p]的值替换为L[i],可证p=f(i),替换B[p]=L[i],并记录最大p即为LIS

#include<cstdio>
#include<cstring>

const int N = 10010;
int l[N],n,f[N],B[N];

int bsrch(int v,int l,int r)
{
	if(v>B[r]) return r+1;
	if(l>=r) return l;
	int m=(l+r)/2;
	if(v<B[m]) return bsrch(v,l,m);
	return bsrch(v,m+1,r);
}

int main()
{
	int cnt = 1;
	for(;scanf("%d",&l[0]) && l[0]>=0;cnt++)
	{
		int i,j,p;
		for(i=1;;i++)
		{
			scanf("%d",l+i);
			if(l[i]<0) break;
		}
		n=i;
		for(i=0;i<n;i++) {f[i]=1;B[i]=0;}
		int ans=0;
		for(i=n-1;i>=0;i--)
		{
			f[i]=bsrch(l[i],1,ans);
			B[f[i]]=l[i];
			if(f[i]>ans) ans=f[i];
		}	
		printf("Test #%d:\n  maximum possible interceptions: %d\n\n",cnt,ans);
	}
} 


192k 0ms

 

参考:http://www.programfan.com/blog/article.asp?id=13086

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值