• BZOJ1069 [SCOI2007]最大土地面积 【凸包 + 旋转卡壳】


    题目链接

    BZOJ1069

    题解

    首先四个点一定在凸包上
    我们枚举对角线,剩下两个点分别是两侧最远的点
    可以三分,复杂度(O(n^2logn))
    可以借鉴旋转卡壳的思想,那两个点随着对角线的一定单调不减,可以用两个指针维护,复杂度(O(n^2))

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define mp(a,b) make_pair<int,int>(a,b)
    #define cls(s) memset(s,0,sizeof(s))
    #define cp pair<int,int>
    #define LL long long int
    using namespace std;
    const int maxn = 2005,maxm = 100005,INF = 1000000000;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    struct point{double x,y;}p[maxn],t[maxn];
    inline bool operator <(const point& a,const point& b){
    	return a.x == b.x ? a.y < b.y : a.x < b.x;
    }
    inline point operator +(const point& a,const point& b){
    	return (point){a.x + b.x,a.y + b.y};
    }
    inline point operator -(const point& a,const point& b){
    	return (point){a.x - b.x,a.y - b.y};
    }
    inline double operator *(const point& a,const point& b){
    	return a.x * b.x + a.y * b.y;
    }
    inline double cross(const point& a,const point& b){
    	return a.x * b.y - a.y * b.x;
    }
    inline double dis(const point& a,const point& b){
    	return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
    }
    inline double S(const point& a,const point& b,const point& c){
    	return fabs(0.5 * cross(c - a,c - b));
    }
    int n,st[maxn],top;
    void cal(){
    	sort(p + 1,p + 1 + n);
    	st[top = 1] = 1;
    	for (int i = 2; i <= n; i++){
    		while (top > 1 && cross(p[i] - p[st[top]],p[st[top]] - p[st[top - 1]]) <= 0)
    			top--;
    		st[++top] = i;
    	}
    	int tmp = top;
    	for (int i = n - 1; i; i--){
    		while (top > tmp && cross(p[i] - p[st[top]],p[st[top]] - p[st[top - 1]]) <= 0)
    			top--;
    		st[++top] = i;
    	}
    	n = --top;
    	for (int i = 1; i <= n; i++) t[i] = p[st[i]];
    	for (int i = 1; i <= n; i++) p[i] = t[i];
    }
    void solve(){
    	if (n == 3){printf("%.3lf",S(p[1],p[2],p[3])); return;}
    	double ans = 0;
    	for (int i = 1; i <= n - 3; i++){
    		int x = i + 1,y = i + 3;
    		for (int j = i + 3; j <= n; j++){
    			if (S(p[i],p[i + 2],p[j]) > S(p[i],p[i + 2],p[y]))
    				y = j;
    		}
    		ans = max(ans,S(p[i],p[i + 2],p[x]) + S(p[i],p[i + 2],p[y]));
    		for (int j = i + 3; j <= n; j++){
    			while (x + 1 < j && S(p[i],p[j],p[x + 1]) > S(p[i],p[j],p[x])) x++;
    			while (y + 1 <= n && S(p[i],p[j],p[y + 1]) > S(p[i],p[j],p[y])) y++;
    			ans = max(ans,S(p[i],p[j],p[x]) + S(p[i],p[j],p[y]));
    		}
    	}
    	printf("%.3lf
    ",ans);
    }
    int main(){
    	n = read();
    	if (n <= 2) {puts("0"); return 0;}
    	REP(i,n) scanf("%lf%lf",&p[i].x,&p[i].y);
    	cal();
    	//REP(i,n) printf("(%lf,%lf)
    ",p[i].x,p[i].y);
    	solve();
    	return 0;
    }
    
    
  • 相关阅读:
    修改CentOS 6.4 root用户的系统默认语言设置
    Xpages学习
    Mysql 执行sql脚本文件
    Errors occurred during the build. Errors running builder 'JavaScript Validator' on project 'XXX'.
    【鸟哥学习笔记】之一:目录的权限问题
    学习C++的一些问题总结
    C# 一些知识点总结(一)_继承,多态,集合,关键字...
    .NET Framework 框架的一些简单介绍
    Winform窗体关闭时判断是否关闭
    SQL Server 数据库的安全管理(登录、角色、权限)
  • 原文地址:https://www.cnblogs.com/Mychael/p/9163711.html
Copyright © 2020-2023  润新知