HDU 6538

题意:给你n个点,选四个点构成四边形,求四边形的面积最大最小值的两倍。

分析:先将点按照x为第一关键词y为第二关键词从小到大排序,然后我们开始取向量,并将所取的所有向量进行极角排序。第一条向量的两个端点在之前排序过的点的序列中是相邻的。这样的序列保证在序列的第一个点到向量的左端点的点距离这条直线单调递减,右侧也一样,那么我们考虑当我们旋转坐标系的时候,画图可知,受影响的点只有之前那条向量上的点,而且根据之前矛盾关系,之前那条的斜率大于现在这条,那么之前那条的两端点到这条线上的距离一个小一个大,那么我们只需要更换这两个点在序列中的位置,即可满足之前的单调性,所以每次旋转坐标系只需要交换上一条的向量两端点在排序后的序列中的位置即可,这样我们就维护出了距离对角线最远和最近的点,最大最小四边形面积也可以得出,也可以用此方法求得最大最小三角形面积。

参考博客:https://www.cnblogs.com/dd-bond/p/10924059.html

同样的题还有BZOJ3707、CodeForces - 1019D

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1e6+10;
int p[2010];
struct Point{
    int x,y,i,j;
    Point(){ x=y=0; }
    Point(int a,int b){ x=a,y=b; }
    Point(int a,int b,Point p){ i=a,j=b,x=p.x,y=p.y; }
    Point operator -(const Point &n)const{ return Point(x-n.x,y-n.y); }
    bool operator <(const Point&n)const{ return x==n.x? y<n.y: x<n.x; }
}point[2010],vec[2*MAXN];

ll cross(Point a,Point b){ return 1ll*a.x*b.y-1ll*a.y*b.x; }

ll check(int i,int j,int k){ return abs(cross(point[j]-point[i],point[k]-point[i])); }

int main(void)
{
    ios::sync_with_stdio(false);    cin.tie(0);   cout.tie(0);
    ll n;
    while(cin>>n){
        ll s1=9e18,s2=0,cnt=0;
        for(int i=0;i<n;i++)    cin>>point[i].x>>point[i].y,p[i]=i;
        if(n<4)    return cout<<0<<' '<<0<<endl,0;
        sort(point,point+n);
        for(int i=0;i<n;i++)
            for(int j=i+1;j<n;j++)
                vec[cnt++]=Point(i,j,point[j]-point[i]);
        sort(vec,vec+cnt,[](Point a,Point b){ return cross(a,b)>0; });
        for(int i=0;i<cnt;i++){
            int a=vec[i].i,b=vec[i].j;
            ///if(p[a]>p[b])    swap(a,b);
            if(p[a]!=0&&p[b]!=n-1)    s2=max(s2,check(p[a],p[b],0)+check(p[a],p[b],n-1));
            if(p[a]!=0&&p[b]!=n-1)    s1=min(s1,check(p[a],p[b],p[a]-1)+check(p[a],p[b],p[b]+1));
            ///交换
            swap(p[a],p[b]);    swap(point[p[a]],point[p[b]]);
        }
        cout<<s1<<' '<<s2<<endl;
    }
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值