Bzoj1591:[Usaco2008 Dec]Largest Fence 最大的围栏:DP

22 篇文章 0 订阅
4 篇文章 0 订阅

题目链接:1591:[Usaco2008 Dec]Largest Fence 最大的围栏

显然不能枚举

考虑dp,每个点肯定都有一个包含他的最大的凸包

观察凸包,存在一条边使得顺时针看凸包上一圈的边极角是递增的,手画一个凸包就可以发现(三象限->四->一->二)

别告诉我你不知道极角是会有负数的

所以我们将点两两连边,将边按照极角排序

设f[i]为包含i的最大凸包上的点的数量,则f[j]=max(f[j],f[i]+1)(i->j有边)

凸包是一个环,边的极角序递增,我们做dp必然会转移到i,最终f[i]就是包含i的最大凸包上的点的数量

初值f[i]=0,剩下的点赋值为极小值,由于是按极角排的序,极角小的边先被更新,所以只要按照拍完序的边进行转移就会得到正确的转移顺序

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=310;
struct Line{
	int u,v; double a;
}l[maxn*maxn];
struct point{
	int x,y;
}p[maxn];
bool cmp(const Line &a,const Line &b){
	return a.a<b.a;
}
int f[maxn],n,N=0,ans=0;

int main(){
	scanf("%d",&n);
	for (int i=1;i<=n;++i) scanf("%d%d",&p[i].x,&p[i].y);
	for (int i=1;i<=n;++i)
	    for (int j=1;j<=n;++j)
	        if (i!=j){
				N++; l[N].u=i; l[N].v=j;
				l[N].a=atan2(p[j].y-p[i].y,p[j].x-p[i].x);
	        }
	 sort(l+1,l+N+1,cmp);
	 for (int i=1;i<=n;++i){
		for (int j=1;j<=n;++j) f[j]=-0x7fffffff;
		f[i]=0;
		for (int j=1;j<=N;++j)
			f[l[j].v]=max(f[l[j].v],f[l[j].u]+1);
		ans=max(ans,f[i]);
	 }
	 printf("%d",ans);
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值