zoukankan      html  css  js  c++  java
  • [JOISC2014]二人の星座

    XVI.[JOISC2014]二人の星座

    这题乍一看,和之前X.[POI2008]TRO-Triangles好像思想差不多;但是实际操作一番并进行了很多失败的尝试后,发现并不能简单应用。

    后来知道了一种判两个(三点不共线的)三角形相离的做法:它们一定存在且只存在两条相同的外割线。(一个三角形的外割线指的是经过其一个顶点且只在该顶点处与整个三角形相交的直线;相同的外割线,就是经过两个三角形各一个节点的上述直线)。具体可以通过画几个三角形自己手工感性理解一下。

    知道该结论就行了。我们考虑枚举该外割线即可(可以通过固定外割线的一端,按照极角大小排序并枚举另一端实现),然后考虑该外割线两端各有多少对节点可以分别与两个端点构成三角形即可。具体操作参见X即可。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ms(x) memset(x,0,sizeof(x))
    typedef long long ll;
    int n,m,col[3010],ss[3],in[3];
    ll res;
    const double pi=acos(-1);
    struct Vector{
    	int x,y;
    	Vector(int X=0,int Y=0){x=X,y=Y;}
    	friend Vector operator +(const Vector &u,const Vector &v){return Vector(u.x+v.x,u.y+v.y);}
    	friend Vector operator -(const Vector &u,const Vector &v){return Vector(u.x-v.x,u.y-v.y);}
    	friend ll operator &(const Vector &u,const Vector &v){return 1ll*u.x*v.y-1ll*u.y*v.x;}//cross times
    	friend ll operator |(const Vector &u,const Vector &v){return 1ll*u.x*v.x+1ll*u.y*v.y;}//point times
    	double operator !()const{return atan2(y,x);}//the angle of a vector
    	friend bool operator <(const Vector &u,const Vector &v){return !u<!v;}
    	void read(){scanf("%d%d",&x,&y);}
    	void print(){printf("(%d,%d)",x,y);}
    }p[3010];
    typedef Vector Point;
    pair<Point,int>q[3010];
    int main(){
    	scanf("%d",&n);
    	for(int i=0;i<n;i++)p[i].read(),scanf("%d",&col[i]),ss[col[i]]++;
    	for(int i=0;i<n;i++){
    		m=0;
    		for(int j=0;j<n;j++)if(i!=j)q[m++]=make_pair(p[j]-p[i],col[j]);
    		sort(q,q+m);
    //		for(int j=0;j<m;j++)q[j].first.print();puts("");
    		int len=-1;
    		for(int a=0,b=0;a<m;a++){
    			in[q[a].second]--;
    			if(len<0)ms(in),len=0,b=(a+1)%m;
    			for(;len<m&&(q[a].first&q[b].first)>0;b=(b+1)%m)in[q[b].second]++,len++;
    //			printf("[%d,%d]\n",a,b);
    //			for(int j=0;j<3;j++)printf("%d ",in[j]);puts("");
    //			for(int j=0;j<3;j++)printf("%d ",ss[j]-in[j]-(q[a].second==j)-(col[i]==j));puts("");
    			ll now=1;
    			for(int j=0;j<3;j++)if(j!=col[i])now*=in[j];
    			for(int j=0;j<3;j++)if(j!=q[a].second)now*=(ss[j]-in[j]-(col[i]==j));
    			res+=now; 
    			len--;
    		}
    	}
    	printf("%lld\n",res>>1);
    	return 0;
    } 
    

  • 相关阅读:
    #公式与实现# Jacobi迭代 Gauss-Seidel迭代
    数据结构-C:二叉树的遍历
    c++
    Unix Systems Programming
    二进制文件读取写入(一)
    关于理论、模型与算法
    《计算机图形学与几何造型导论》读书笔记1
    petaPar培训文档
    等参元的高斯积分详解
    水平集函数具体实现
  • 原文地址:https://www.cnblogs.com/Troverld/p/14619360.html
Copyright © 2011-2022 走看看