Topcoder SRM 641 Div1 250(另辟蹊径,排除法)

来源:互联网 发布:中北大学宿舍网络 编辑:程序博客网 时间:2024/04/29 12:14

Problem Statement

 We have chosen a finite set of points in the plane. You are given their coordinates in the vector <int>sx and y: for each valid i, there is a point with coordinates (x[i],y[i]). We are interested in triangles with the following properties:
  • Each vertex of the triangle is one of our chosen points.
  • The point (0,0) lies inside the triangle.
Return the number of such triangles. Note that the constraints guarantee that there are no degenerate triangles and that the point (0,0) never lies on the boundary of a triangle.

Definition

 Class:TrianglesContainOriginMethod:countParameters:vector <int>, vector <int>Returns:long longMethod signature:long long count(vector <int> x, vector <int> y)(be sure your method is public)

Limits

 Time limit (s):2.000Memory limit (MB):256Stack limit (MB):256

Constraints

-x and y will contain between 3 and 2500 elements, inclusive.-x and y will contain the same number of elements.-Each element of x and y will be between -10,000 and 10,000, inclusive.-No two points will be the same.-No three points will be collinear.-No point will be on the origin.-There will be no two points P and Q such that P, Q, and the origin are collinear.

Examples

0)  
{-1,-1,1}
{1,-1,0}
Returns: 1
There is exactly one possible triangle. It does contain the origin.1)  
{-1,-1,1,2}
{1,-1,2,-1}
Returns: 2
There are four possible triangles. Two of them contain the origin. One is the triangle with vertices in (-1,1), (-1,-1), and (2,-1). The other is the triangle with vertices in (-1,-1), (1,2), and (2,-1).2)  
{-1,-2,3,3,2,1}
{-2,-1,1,2,3,3}
Returns: 8
3)  
{1,5,10,5,-5,7,-9,-6,-3,0,8,8,1,-4,7,-3,10,9,-6}
{5,-6,-3,4,-2,-8,-7,2,7,4,2,0,-4,-8,7,5,-5,-2,-9}
Returns: 256


一个二维平面,给n个点,保证n个点两两不重合,保证没有点与原点重合,保证没有3点共线,保证没有两点和原点共线..

求有多少个三角形可以使得原点在三角形内。


此题并不通用,因为限制条件太多,不过解起来也比较好办。根据此题保证的条件,任意3个点都可以构成一个三角形,并且不可能有两个三角形重合,则一共有C(n,3)个三角形,C(n,3)个三角形中有的围住了原点,有的没有,只需减去没有的数量就是答案了。怎么统计没有的呢?枚举任意一个点A,其与原点可以构成一个向量OA,其余点B与原点构成的向量OB,OA与OB一定不共线,OA所在的直线把平面分成了两个部分,不妨以左部分为关键平面,算出平面中点的个数m,m个点中任意两个点可以和A构成一个唯一的三角形,则有C(m,2)个三角形,可以说明这C(m,2)个三角形一定不围住原点。可以说明对于每个OA,只需统计一半边中三角形个数,然后用C(n,3)减去每个C(m,2)就是答案。


代码如下:(建议自己写,不要看)

//Hello. I'm Peter.#include<cstdio>#include<iostream>#include<sstream>#include<cstring>#include<string>#include<cmath>#include<cstdlib>#include<algorithm>#include<functional>#include<cctype>#include<ctime>#include<stack>#include<queue>#include<vector>#include<set>#include<map>using namespace std;typedef long long ll;typedef long double ld;#define peter cout<<"i am peter"<<endl#define input freopen("data.txt","r",stdin)#define randin srand((unsigned int)time(NULL))#define INT (0x3f3f3f3f)*2#define LL (0x3f3f3f3f3f3f3f3f)*2#define gsize(a) (int)a.size()#define len(a) (int)strlen(a)#define slen(s) (int)s.length()#define pb(a) push_back(a)#define clr(a) memset(a,0,sizeof(a))#define clr_minus1(a) memset(a,-1,sizeof(a))#define clr_INT(a) memset(a,INT,sizeof(a))#define clr_true(a) memset(a,true,sizeof(a))#define clr_false(a) memset(a,false,sizeof(a))#define clr_queue(q) while(!q.empty()) q.pop()#define clr_stack(s) while(!s.empty()) s.pop()#define rep(i, a, b) for (int i = a; i < b; i++)#define dep(i, a, b) for (int i = a; i > b; i--)#define repin(i, a, b) for (int i = a; i <= b; i++)#define depin(i, a, b) for (int i = a; i >= b; i--)#define pi acos(-1.0)#define eps 1e-6#define MOD 1000000007#define MAXN#define N 101000#define Mstruct Point{    double x,y;    Point(){};    Point(double xx,double yy):x(xx),y(yy){};}p[N];typedef Point Vector;double sq(double x){//x^2    return x*x;}int dcmp(double x){//判断x正负或为0    if(fabs(x)<eps) return 0;    else if(x<0) return -1;    else return 1;}Vector operator +(const Vector a,const Vector b){//两向量相加    return Vector(a.x+b.x,a.y+b.y);}Vector operator -(const Vector a,const Vector b){//两向量相减    return Vector(a.x-b.x,a.y-b.y);}bool operator ==(const Vector a,const Vector b){//判断两点或两向量是否一致    return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0;}double operator *(const Vector a,const Vector b){//两向量点乘    return a.x*b.x+a.y*b.y;}double operator &(const Vector a,const Vector b){//两向量叉积    return a.x*b.y-a.y*b.x;}Vector operator *(const Vector b,const double a){//一个数*一个向量    return Vector(a*b.x,a*b.y);}Vector operator *(const double a,const Vector b){//一个向量*一个数    return Vector(a*b.x,a*b.y);}class TrianglesContainOrigin{public:    long long count(vector <int> x, vector <int> y){        ll len=gsize(x);        rep(i,0,len){            p[i]=Point(x[i],y[i]);        }        Point ori(0,0);        ll res=len*(len-1)*(len-2)/(6LL);        rep(i,0,len){            Vector v1=p[i]-ori;            ll num=0;            rep(j,0,len){                if(i==j) continue;                Vector v2=p[j]-ori;                if(dcmp(v1&v2)>0){                    num+=1;                }            }            num=num*(num-1)>>1LL;            res-=num;        }        return res;    }};


0 0