• 【BZOJ】1069: [SCOI2007]最大土地面积(凸包+旋转卡壳)


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

    显然这四个点在凸包上,然后枚举两个点找上下最大的三角形即可。

    找三角形表示只想到三分QAQ。。。。。。。

    看了题解发现。。。。这是单调的。。。。直接扫。。。然后,这货叫“旋转卡壳”?是qia还是ka。。。。

    自己一开始写的wa了。。。。。。。。然后照标程写,,又wa了。。。。

    后来发现是凸包写渣了QAQ。。。自己原来的找三角形是没问题的。。。我好sb。。。。。

    可是,为嘛凸包这样写会错。

    cross(b[cnt], a[i], b[cnt-1])<=0变成cross(a[i], b[cnt], b[cnt-1])>0为嘛会错!!!!!!!

    //upd:^(*&%*^^我为什么那么逗。。。。不应该是>=0吗。。。。。。。。。。。。。

    2015.4.20 upd:

    那是因为数据中有重复点!去掉重复点就能a啦!

    如果凸包求的是允许三点共线的,那么数据中不能出现重复点!(因为这样会使得求凸壳出错!


    两个写法:

    自己yy的(凸包那里改了)

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <set>
    #include <map>
    using namespace std;
    typedef long long ll;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define error(x) (!(x)?puts("error"):0)
    #define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    
    const int N=2005;
    struct dat { double x, y; }a[N], b[N];
    int n, cnt;
    double suml[N][N], sumr[N][N];
    bool cmp(const dat &a, const dat &b) { return a.x<b.x; }
    double cross(const dat &a, const dat &b, const dat &c) {
    	static dat x, y;
    	x.x=a.x-c.x; x.y=a.y-c.y;
    	y.x=b.x-c.x; y.y=b.y-c.y;
    	return x.x*y.y-y.x*x.y;
    }
    void tb() {
    	sort(a+1, a+1+n, cmp);
    	for1(i, 1, n) {
    		while(cnt>1 && cross(b[cnt], a[i], b[cnt-1])<=0) --cnt;
    		b[++cnt]=a[i];
    	}
    	int k=cnt;
    	for3(i, n-1, 1) {
    		while(cnt>k && cross(b[cnt], a[i], b[cnt-1])<=0) --cnt;
    		b[++cnt]=a[i];
    	}
    	if(n>1) --cnt;
    }
    double S(const dat &a, const dat &b, const dat &c) { return abs(cross(a, b, c))/2.0; }
    void work() {
    	int mid, nxt, j;
    	for1(i, 1, n) {
    		mid=(i%n)+1;
    		for1(t, 1, n-2) {
    			j=(i+t)%n+1;
    			nxt=(mid%n)+1;
    			while(nxt!=j && S(b[i], b[j], b[nxt])>=S(b[i], b[j], b[mid])) { mid=nxt; nxt=(mid%n)+1; }
    			suml[i][j]=S(b[i], b[j], b[mid]); //printf("%d %d chose:%d: S:%.3f
    ", i, j, mid, suml[i][j]);
    		}
    		mid=(i-2+n)%n+1;
    		for1(t, 1, n-2) {
    			j=(i-2+n-t+n)%n+1;
    			nxt=(mid-2+n)%n+1;
    			while(nxt!=j && S(b[i], b[j], b[nxt])>=S(b[i], b[j], b[mid])) { mid=nxt; nxt=((mid-2+n)%n)+1; }
    			sumr[i][j]=S(b[i], b[j], b[mid]);
    		}
    	}
    }
    
    int main() {
    	read(n);
    	for1(i, 1, n) scanf("%lf%lf", &a[i].x, &a[i].y);
    	tb(); n=cnt;
    	//for1(i, 1, n) printf("%.2f %.2f
    ", b[i].x, b[i].y);
    	work(); double ans=0;
    	for1(i, 1, n) for1(j, 1, n) if(suml[i][j] && sumr[i][j]) ans=max(ans, suml[i][j]+sumr[i][j]);
    	printf("%.3f", ans);
    	return 0;
    }
    

    照hzwer神犇的:

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <set>
    #include <map>
    using namespace std;
    typedef long long ll;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define error(x) (!(x)?puts("error"):0)
    #define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    
    const int N=2005;
    struct dat { double x, y; }a[N], b[N];
    int n, cnt;
    bool cmp(const dat &a, const dat &b) { return a.x<b.x; }
    double cross(const dat &a, const dat &b, const dat &c) {
    	static dat x, y;
    	x.x=a.x-c.x; x.y=a.y-c.y;
    	y.x=b.x-c.x; y.y=b.y-c.y;
    	return x.x*y.y-y.x*x.y;
    }
    void tb() {
    	sort(a+1, a+1+n, cmp);
    	for1(i, 1, n) {
    		while(cnt>1 && cross(b[cnt], a[i], b[cnt-1])<=0) --cnt;
    		b[++cnt]=a[i];
    	}
    	int k=cnt;
    	for3(i, n-1, 1) {
    		while(cnt>k && cross(b[cnt], a[i], b[cnt-1])<=0) --cnt;
    		b[++cnt]=a[i];
    	}
    	if(n>1) --cnt;
    }
    double S(const dat &a, const dat &b, const dat &c) { return abs(cross(a, b, c)); }
    double work() {
    	b[cnt+1]=b[1];
    	int dmid, umid;
    	double ret=0;
    	for1(i, 1, n) {
    		dmid=(i%n)+1, umid=((i+2)%n)+1;
    		for1(j, i+2, n) {
    			while((dmid%n)+1!=j && S(b[i], b[j], b[dmid+1])>=S(b[i], b[j], b[dmid])) dmid=(dmid%n)+1;
    			while((umid%n)+1!=i && S(b[i], b[j], b[umid+1])>=S(b[i], b[j], b[umid])) umid=(umid%n)+1;
    			ret=max(ret, S(b[i], b[j], b[dmid])+S(b[i], b[j], b[umid]));//printf("%d %d chose:%d: S:%.3f
    ", i, j, mid, suml[i][j]);
    		}
    	}
    	return ret/2.0;
    }
    
    int main() {
    	read(n);
    	for1(i, 1, n) scanf("%lf%lf", &a[i].x, &a[i].y);
    	tb(); n=cnt;
    	//for1(i, 1, n) printf("%.2f %.2f
    ", b[i].x, b[i].y);
    	printf("%.3f", work());
    	return 0;
    }
    

      


    Description

    在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成的多边形面积最大。

    Input

    第1行一个正整数N,接下来N行,每行2个数x,y,表示该点的横坐标和纵坐标。

    Output

    最大的多边形面积,答案精确到小数点后3位。

    Sample Input

    5
    0 0
    1 0
    1 1
    0 1
    0.5 0.5

    Sample Output

    1.000

    HINT

    数据范围 n<=2000, |x|,|y|<=100000

    Source

     
  • 相关阅读:
    NBUT 1120 Reimu's Teleport (线段树)
    NBUT 1119 Patchouli's Books (STL应用)
    NBUT 1118 Marisa's Affair (排序统计,水)
    NBUT 1117 Kotiya's Incantation(字符输入处理)
    NBUT 1115 Cirno's Trick (水)
    NBUT 1114 Alice's Puppets(排序统计,水)
    188 Best Time to Buy and Sell Stock IV 买卖股票的最佳时机 IV
    187 Repeated DNA Sequences 重复的DNA序列
    179 Largest Number 把数组排成最大的数
    174 Dungeon Game 地下城游戏
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4162821.html
Copyright © 2020-2023  润新知