BZOJ1591 & 洛谷2924:[USACO2008 DEC]Largest Fence 最大的围栏——题解

http://www.lydsy.com/JudgeOnline/problem.php?id=1591

https://www.luogu.org/problemnew/show/P2924#sub

有n(5≤n≤250)个栅栏点,FJ需要围成一个栅栏圈,这个圈是一个凸包并且凸包上的点最多。

这题题解写的如此之玄幻,题目看起来如此之不可做……

然而实际很简单……看了半天题解发现不如看他代码。

我们考虑我们是怎么构造凸包的,就是通过点的极角排序来判断这个点所引出的线应该往哪里转(或者可能不取这个点)……

那么我们显然可以对边进行极角排序,然后利用这些边来构造凸包。

首先我们枚举点a作为这个凸包的最左点,dp[i][j]表示(i,j)这条边作为凸包a的最后一条边时一共有多少点。

那么我们枚举k,显然如果满足极角排序中(k,i)<(i,j)那么(k,i)(i,j)就可以作为这个凸包的两条边,我们就可以dp[i][j]=max{dp[k][i]+1}

但是显然是O(n^4)的,考虑优化。

如果我们可以求出g[i]=max{dp[k][i]}显然可以O(n^2)。

于是对所有的边进行极角排序,枚举排序后的边端点x,y有g[y]=max(g[y],g[x]+1)(显然,可感性理解,初值g[a]=0,其余为-INF),同时转移dp即可。

#include<cstdio>
#include<queue>
#include<cctype>
#include<cstring>
#include<stack>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=260;
const int INF=2147483647;
struct point{
    int x,y;
}p[N],q[N];
struct line{
    point v;
    int x,y;
}v[N*N];
int n,cnt,per[N],l,g[N],dp[N][N];
inline point getmag(point a,point b){
    point s;
    s.x=b.x-a.x;s.y=b.y-a.y;
    return s;
}
inline int multiX(point a,point b){
    return a.x*b.y-b.x*a.y;
}
inline bool cmp(line a,line b){
    return multiX(a.v,b.v)<0;
}
inline void init(){
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=n;i++)g[i]=-INF;
}
int solve(){
    int ans=0;
    for(int i=1;i<=n;i++){
        init();
        g[i]=0;
        for(int j=1;j<=cnt;j++){
            int px=v[j].x,py=v[j].y;
            dp[px][py]=max(dp[px][py],g[px]+1);
            if(py!=i)g[py]=max(g[py],g[px]+1);
        }
        for(int j=1;j<=n;j++)ans=max(ans,dp[j][i]);
    }
    return ans;
}
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){
                v[++cnt].x=i;
                v[cnt].y=j;
                v[cnt].v=getmag(p[i],p[j]);
            }
        }
    }
    sort(v+1,v+cnt+1,cmp);
    printf("%d\n",solve());
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++


+本文作者:luyouqi233。               +


+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+


+++++++++++++++++++++++++++++++++++++++++++

 
posted @ 2018-01-31 20:19  luyouqi233  阅读(351)  评论(0编辑  收藏  举报