zoukankan      html  css  js  c++  java
  • bzoj 1132: [POI2008]Tro 计算几何

    题目大意:

    平面上有N个点. 求出所有以这N个点为顶点的三角形的面积和 N<=3000

    题解

    我们看到了n的范围,于是我们就知道这一定不是一个线性算法
    所以我们尝试枚举三角形的一个点,那么我们现在要对每一个点i,求
    (sum_{j,k eq i}(overrightarrow{p_ip_j})*(overrightarrow{p_ip_k}))
    其中*表示叉积
    然后我们发现这是一个对二元对的某种操作求和的一种
    我们可以想到将其转化为

    [sum_{j,k eq i}abs((overrightarrow{p_ip_j})*sum(overrightarrow{p_ip_k})) ]

    我们拆开叉积的表达式即(x_1*y_2 - y_1*x_2)我们发现是可以这么拆的
    但是我们每次累加的时候实际上是取abs的,所以实际上并不能这么加
    所以我们尝试拆开abs
    我们发现只要我们用一个恰当的顺序枚举j,k就可以不用取abs即可
    所以可以做到(O(n^2logn))瓶颈在于极角排序

    #include <cstdio>
    #include <iomanip>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &x){
    	x=0;char ch;bool flag = false;
    	while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    	while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
    inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
    const int maxn = 3010;
    const double eps = 1e-9;
    struct Point{
    	ll x,y;
    	double k;
    	Point(const ll &a=0,const ll &b=0){x=a;y=b;}
    };
    inline bool cmp1(const Point &a,const Point &b){
    	return a.x == b.x  ? a.y < b.y : a.x < b.x;
    }
    inline bool cmp2(const Point &a,const Point &b){
    	return a.k < b.k;
    }
    typedef Point Vector;
    inline Vector operator + (const Vector &a,const Vector &b){
    	return Vector(a.x + b.x,a.y + b.y);
    }
    inline Vector operator - (const Vector &a,const Vector &b){
    	return Vector(a.x - b.x,a.y - b.y);
    }
    inline ll cross(const Vector &a,const Vector &b){
    	return a.x*b.y - a.y*b.x;
    }
    Point s[maxn],p[maxn];
    int cnt = 0;
    int main(){
    	int n;read(n);
    	for(int i=1;i<=n;++i){
    		read(p[i].x);read(p[i].y);
    	}sort(p+1,p+n+1,cmp1);
    	ll ans = 0;
    	for(int i=1;i<=n;++i){
    		cnt = 0;
    		for(int j=i+1;j<=n;++j){
    			s[++cnt] = p[j] - p[i];
    			if(p[j].x == p[i].x) s[cnt].k = 1e10;
    			else s[cnt].k = (double)(p[i].y - p[j].y)/(double)(p[i].x - p[j].x);
    		}sort(s+1,s+cnt+1,cmp2);
    		Point sum;
    		for(int j=cnt;j>=1;--j){
    			ans += cross(s[j],sum);
    			sum = sum + s[j];
    		}
    	}printf("%lld.",ans>>1);
    	if(ans & 1) puts("5");
    	else puts("0");
    	getchar();getchar();
    	return 0;
    }
    

    并且在做题的时候发现了一些有趣的事情

    long long x = 100000000000000;
    printf("%d
    ",((long long)((double)x)) == x);
    

    会输出0哈哈哈哈哈哈哈哈哈哈哈哈
    为了这个lz拍了30mins的标程。。。

  • 相关阅读:
    vue中的 computed 和 watch 的区别
    mysql8.0 初始化数据库及表名大小写问题
    sql server alwayson 调整数据文件路径
    zabbix 自定义监控 SQL Server
    mysql 创建用户及授权
    mysql 设置从库只读模式
    mysql8.0 主从复制安装及配置
    centos8.0安装mysql8.0
    centos8替换阿里数据源
    npm publish 报错 【you or one of your dependencies are requesting a package version that is forbidden by your security policy】
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6440192.html
Copyright © 2011-2022 走看看