2016 Multi-University Training Contest 2 1005 hdu 5738 计算几何

来源:互联网 发布:js vr 插件 互动 编辑:程序博客网 时间:2024/06/06 00:34



链接:戳这里

Eureka
Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Problem Description
Professor Zhang draws n points on the plane, which are conveniently labeled by 1,2,...,n. The i-th point is at (xi,yi). Professor Zhang wants to know the number of best sets. As the value could be very large, print it modulo 109+7.

A set P (P contains the label of the points) is called best set if and only if there are at least one best pair in P. Two numbers u and v (u,v∈P,u≠v) are called best pair, if for every w∈P, f(u,v)≥g(u,v,w), where f(u,v)=(xu−xv)2+(yu−yv)2−−−−−−−−−−−−−−−−−−−√ and g(u,v,w)=f(u,v)+f(v,w)+f(w,u)2.
 
Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first line contains an integer n (1≤n≤1000) -- then number of points.

Each of the following n lines contains two integers xi and yi (−109≤xi,yi≤109) -- coordinates of the i-th point.
 
Output
For each test case, output an integer denoting the answer.
 
Sample Input
3
3
1 1
1 1
1 1
3
0 0
0 1
1 0
1
0 0
 
Sample Output
4
3
0
 

思路:

先去重,题目要求的集合是一条线段。并且u,v是线段的两个端点。那么对于点集的每一条线段,都统计每一条的贡献

设线段上有k个点,那么贡献为即(C(k,2)+C(k,3)+...+C(k,k))=2^k-1-k。但是在多条线段的交点处如果恰好是g个重点存在

那么我们需要减去多算的,设该重点恰好在m条线段上,那么多算了(m-1)次。多算的贡献为(m-1)*((2^g)-g-1)

问题就变成了一条线段上有多少个点以及一个点出现在多少线段上。直接n*nlogn处理

注意卡精度,开long double 吧


代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<string>#include<vector>#include <ctime>#include<queue>#include<set>#include<map>#include<stack>#include<iomanip>#include<cmath>#define mst(ss,b) memset((ss),(b),sizeof(ss))#define maxn 0x3f3f3f3f#define MAX 1000100#pragma comment(linker, "/STACK:102400000,102400000")typedef long long ll;typedef unsigned long long ull;#define mod 1000000007#define INF (1ll<<60)-1using namespace std;const long double eps=1e-10;int dcmp(long double x){    if(fabs(x)<=eps) return 0;    return x<0?-1:1;}struct point{    long double x,y;    point(long double x=0,long double y=0):x(x),y(y){}    bool operator < (const point &a)const{        if(dcmp(x-a.x)==0) return y<a.y;        return x<a.x;    }};bool operator == (const point &a,const point &b) {    if(fabs(a.x-b.x)<=eps && fabs(a.y-b.y)<=eps)        return true;    return false;}point s[1010],p[1010];struct edge{    long double k,b;    int A,B;    bool operator < (const edge &a)const{        if(dcmp(k-a.k)==0) return b<a.b;        return k<a.k;    }}e[1000100];map<point,int> mp;int q[1010];ll Pow[1010];int main(){    Pow[0]=1LL;    for(int i=1;i<=1000;i++) Pow[i]=Pow[i-1]*2LL%mod;    int T,n;    scanf("%d",&T);    while(T--){        mp.clear();        scanf("%d",&n);        for(int i=1;i<=n;i++) {            cin>>s[i].x>>s[i].y;            mp[s[i]]++;        }        sort(s+1,s+n+1);        int cnt=0;        for(int i=1;i<=n;i++){            while(i+1<=n && s[i]==s[i+1]) i++;            p[++cnt]=s[i];        }        n=cnt;        cnt=0;        for(int i=1;i<=n;i++){            for(int j=i+1;j<=n;j++){                point a=p[i],b=p[j];                if(dcmp(a.x-b.x)==0){                    e[++cnt].k=INF*1.0;                    e[cnt].b=a.x;                } else {                    e[++cnt].k=(a.y-b.y)/(a.x-b.x);                    e[cnt].b=a.y-e[cnt].k*a.x;                }                e[cnt].A=i;                e[cnt].B=j;            }        }        sort(e+1,e+cnt+1);        ll ANS=0;        mst(q,0);        for(int i=1;i<=cnt;i++){            int l=i;            while(dcmp(e[i].k-e[i+1].k)==0 && dcmp(e[i].b-e[i+1].b)==0 && i+1<=cnt){                i++;            }            int ans=0;            for(int j=l;j<=i;j++){                if(q[e[j].A]==0){                    ans+=mp[p[e[j].A]];                    q[e[j].A]=1;                }                if(q[e[j].B]==0){                    ans+=mp[p[e[j].B]];                    q[e[j].B]=1;                }            }            ANS=((ANS+Pow[ans]-1-ans)%mod+mod)%mod;            for(int j=l;j<=i;j++){                q[e[j].A]=0;                q[e[j].B]=0;            }        }        for(int i=1;i<=n;i++){            int tot=0,Num=0;            for(int j=1;j<=n;j++){                if(i==j) continue;                point a=p[i],b=p[j];                if(dcmp(a.x-b.x)==0){                    e[++tot].k=INF*1.0;                    e[tot].b=a.x;                } else {                    e[++tot].k=(a.y-b.y)/(a.x-b.x);                    e[tot].b=a.y-e[tot].k*a.x;                }            }            sort(e+1,e+tot+1);            for(int j=2;j<=tot;j++){                if(dcmp(e[j].k-e[j-1].k)==0 && dcmp(e[j].b-e[j-1].b)==0) continue;                Num++;            }            if (tot==0) ANS=(ANS+Pow[mp[p[i]]]-1-mp[p[i]])%mod;            else if(Num==0) {              ///  if(n>1) continue;             ///   ANS=((ANS+Pow[mp[p[i]]]-1-mp[p[i]])%mod+mod)%mod;            } else {                ANS=((ANS-Num*(Pow[mp[p[i]]]-1-mp[p[i]])%mod+mod)%mod+mod)%mod;            }        }        printf("%I64d\n",ANS);    }    return 0;}/*1051 02 03 04 05 031 11 11 130 00 11 010 072 54 44 42 22 22 24 192 52 54 44 44 44 12 22 22 2*/




0 0
原创粉丝点击