bzoj3707: 圈地

Posted jessie-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3707: 圈地相关的知识,希望对你有一定的参考价值。

题目描述:

$2$ 维平面上有 $n$ 个木桩,黄学长有一次圈地的机会并得到圈到的土地,为了体现他的高风亮节,他要使他圈到的土地面积尽量小。圈地需要圈一个至少 $3$ 个点的多边形,多边形的顶点就是一个木桩,圈得的土地就是这个多边形内部的土地。(因为黄学长非常的神,所以他允许圈出的第 $n$ 点共线,那样面积算 $0$)

思路:

枚举每一条边,考虑这条边作为y轴坐标的大小排序,把边按斜率排序,每次转换边的时候之有这条边的两个端点的大小相对位置会发生变化,排名互换,维护这种变化。

以下代码:

技术图片
#include<bits/stdc++.h>
#define il inline
#define db double
#define _(d) while(d(isdigit(ch=getchar())))
using namespace std;
const int N=1005;
db ans=1e60;
int n,tot,pos[N],rk[N];
struct node{
    db x,y;
}t[N];
struct data{
    int x,y;db k;
}f[N*N];
il int read(){
    int x,f=1;char ch;
    _(!)ch==-?f=-1:f;x=ch^48;
    _()x=(x<<1)+(x<<3)+(ch^48);
    return f*x;
}
bool cmp(node t1,node t2){
    return (t1.x<t2.x);
}
bool cmp1(data t1,data t2){
    return t1.k<t2.k;
}
node operator-(node a,node b){
    return (node){a.x-b.x,a.y-b.y};
}
il db cross(node a,node b){
    return a.x*b.y-a.y*b.x;
}
il db cal(int a,int b,int c){
    return cross(t[a]-t[c],t[b]-t[c]);
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)t[i].x=read(),t[i].y=read();
    sort(t+1,t+1+n,cmp);
    for(int i=1;i<n;i++){
        for(int j=i+1;j<=n;j++){
            f[++tot].x=i;f[tot].y=j;
            f[tot].k=(t[j].y-t[i].y)/(t[j].x-t[i].x);
        }
    }
    for(int i=1;i<=n;i++)pos[i]=rk[i]=i;
    sort(f+1,f+1+tot,cmp1);
    for(int i=1;i<=tot;i++){
        int x=f[i].x,y=f[i].y;
        if(pos[x]>pos[y])swap(x,y);
        if(pos[x]>1)
            ans=fmin(ans,fabs(cal(x,y,rk[pos[x]-1])));
        if(pos[y]<n)
            ans=fmin(ans,fabs(cal(x,y,rk[pos[y]+1])));
        swap(pos[x],pos[y]);
        swap(rk[pos[x]],rk[pos[y]]);
    }
    printf("%.2lf
",ans/2.0);
    return 0;
}
View Code

 

以上是关于bzoj3707: 圈地的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 2132: 圈地计划

BZOJ2132: 圈地计划

BZOJ2132圈地计划(最小割)

BZOJ2132圈地计划 最小割

[BZOJ2132] 圈地计划

BZOJ 2132 圈地计划(最小割)BZOJ 修复工程