HDU - 546 D - Manors

Some famous theoretical scientists with their wives bought 40952 acres of Prairie Nebraska. They describe it as a square of length 4095. Now they want to build their private manors. Each theoretical scientist with his wife (for example, the i-th couple) select m fixed positions in the square, denoted by ( x i 1 , y i 1 ) , ( x i 2 , y i 2 ) , ⋯ , ( x i m , y i m ) (x_{i1},y_{i1}),(x_{i2},y_{i2}),⋯,(x_{im},y_{im}) (xi1,yi1),(xi2,yi2),,(xim,yim), to put their own flags. We have known that the gravity centres of flags for two different theoretical scientists are distinct.
For every inch of land in this square, the influence of the i-th theoretical scientists and his wife, denoted by I i ( ( x , y ) ) I_i((x,y)) Ii((x,y)), is defined as
I i ( ( x , y ) ) = { 1 m ∑ j = 1 m ( ( x − x i j ) 2 + ( y − y i j ) 2 ) } − 1 . I_i((x,y))=\{\frac1m\sum_{j=1}^m((x−x_{ij})^2+(y−y_{ij})^2)\}^{−1}. Ii((x,y))={m1j=1m((xxij)2+(yyij)2)}1.
The couple with the highest influence has the ownership. Your mission is to compute the areas of each private manors.
Input
The input contains several test cases. The first line of the input is a single integer t (t≤10) which is the number of test cases. Then t test cases follow.
Each test case contains several lines. The first line contains the integer n (1≤n≤100) which is the number of theoretical scientists, and the integer m (1≤m≤2000). The i-th line of the next n lines contains 2m integers x 1 , y 1 , x 2 , y 2 , ⋯ , x m , y m x_1,y_1,x_2,y_2,⋯,x_m,y_m x1,y1,x2,y2,,xm,ym between 0 to 4095 which correspond to the positions of m flags belonging to the i-th theoretical scientist and his wife.
Output
For each test case, you should output the areas of each manors in one line.
You need to do decimals to round up and round down numbers (omitting decimal fractions smaller than 0.5 and counting all others, including 0.5, as 1).
Sample Input
2
4 1
1 1
1 3
3 1
3 3
2 2
1 1 1 3
2 1 3 2
Sample Output
Case #1: 4 8186 8186 16752649
Case #2: 2798933 13970093

题意很易懂, 有n个科学家争地盘, 他们各在平面上立了m个flags, 每个flag都会影响每一片土地的重力, 谁对一块土地的影响最大这块土地就归谁.
通过对题目给的公式进行化简就能得到多个不等式, 每个科学家进行一次半平面交求核面积就完事了.

const int MAXN=1e3+10;
const double EPS=1e-4;
const double PI=acos(-1);
inline int sgn(double a){ return a < -EPS ? -1 : a > EPS; }
inline int cmp(double a, double b){ return sgn(a-b); }
long long mod=1e9+7;
int n,m,T;
struct Point;
struct Line;
typedef Point Vector;

struct Point{
    double x,y;
    Point(){}
    Point(double a, double b):x(a),y(b){}
    double len(){return sqrt(x*x+y*y);}
    Point operator+(Vector v){return {x+v.x,y+v.y};}
    Vector operator-(Point p){return {x-p.x,y-p.y};}
    double operator^(Vector v){return x*v.y-y*v.x;}//叉乘
    double operator*(Vector v){return x*v.x+y*v.y;}//点乘
    Vector operator*(double d){return {x*d,y*d};}
    Vector operator/(double d){return {x/d,y/d};}
    bool operator==(Point p){return cmp(x,p.x)==0&&cmp(y,p.y)==0;}
    bool operator<(Point p){if(cmp(x,p.x)==0) return y<p.y;return x<p.x;}
};
struct Line{
    Line(){}
    Line(Point a,Point b){s=a;e=b;ang=atan2(e.y-s.y,e.x-s.x);}
    Point operator &(Line &b){
        double t=((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
        return s+(e-s)*t;
    }
    bool operator<(Line l){
        return ang<l.ang;
    }
    Point s,e;
    double ang;
};
bool HPIcmp(Line a,Line b) {
    if (fabs(a.ang - b.ang) > EPS)return a.ang < b.ang;
    else return ((a.s - b.s) ^ (b.e - b.s)) < 0;
}
struct halfplanes{
    int n;
    Line line[MAXN];
    Point p[MAXN];
    Line Q[MAXN];
    int head,tail;
    double HPI() {
        sort(line+1, line+n+1, HPIcmp);
        int tot = 1;
        for (int i = 2; i <= n; i++)
            if (fabs(line[i].ang - line[i - 1].ang) > EPS) //去掉斜率重复的
                line[++tot] = line[i];
        head = 1, tail = 2;
        Q[1] = line[1];Q[2] = line[2];
        for (int i = 3; i <= tot; i++) {
            if (fabs((Q[tail].e - Q[tail].s) ^ (Q[tail - 1].e - Q[tail - 1].s)) < EPS ||
                fabs((Q[head].e - Q[head].s) ^ (Q[head + 1].e - Q[head + 1].s)) < EPS)
                return 0;
            while (head < tail && (((Q[tail] & Q[tail - 1]) -
                                    line[i].s) ^ (line[i].e - line[i].s)) > EPS)
                tail--;
            while (head < tail && (((Q[head] & Q[head + 1]) -
                                    line[i].s) ^ (line[i].e - line[i].s)) > EPS)
                head++;
            Q[++tail] = line[i];
        }
        while (head < tail && (((Q[tail] & Q[tail - 1]) -
                                Q[head].s) ^ (Q[head].e - Q[head].s)) > EPS)
            tail--;
        while (head < tail && (((Q[head] & Q[head + 1]) -
                                Q[tail].s) ^ (Q[tail].e - Q[tail].s)) > EPS)
            head++;
        if (tail <= head + 1) return 0;
        int resn=0;
        for(int i = head; i < tail; i++)
            p[++resn] = Q[i]&Q[i+1];
        if(head < tail - 1)
            p[++resn] = Q[head]&Q[tail];
        double ret=0;
        for(int i=1;i<=resn;i++)
            ret+=(p[i]^p[i%resn+1]);
        return fabs(ret)/2;
    }
}hpi;

double X[105],Y[105],XX[105],YY[105];
void solve(){
    for(int i=1;i<=n;i++){
        hpi.n=0;
        hpi.line[++hpi.n]={{0,0},{4095,0}};
        hpi.line[++hpi.n]={{4095,0},{4095,4095}};
        hpi.line[++hpi.n]={{4095,4095},{0,4095}};
        hpi.line[++hpi.n]={{0,4095},{0,0}};
        for(int j=1;j<=n;j++){
            if(i==j) continue;
            double a=0,b=0,c=0;
            a=2*(X[i]-X[j]);
            b=2*(Y[i]-Y[j]);
            c=XX[j]+YY[j]-XX[i]-YY[i];

            Point pp;
            if(sgn(a)==0){
                pp={0,-c/b};
            }else{
                pp={-c/a,0};
            }
            Vector v={b,-a};
            hpi.line[++hpi.n]={pp,pp+v};

//            Vector v=Vector(b,-a);//
//            Point p;
//            if(fabs(a)>fabs(b)) p=Point(-c/a,0);
//            else p=Point(0,-c/b);
//            hpi.line[++hpi.n]=Line(p,p+v);
        }
        double sum=hpi.HPI();
        printf(" %d",(int)(sum+0.5));

    }
}

void init(){
    scanf("%d%d",&n,&m);
    double x,y;
    for(int i=1;i<=n;i++) {
        X[i] = Y[i] = XX[i] = YY[i] = 0;
        for (int j = 1; j <= m; j++) {
            scanf("%lf%lf", &x, &y);
            X[i] += x;
            Y[i] += y;
            XX[i] += x * x;
            YY[i] += y * y;
        }
    }
}
int main(){
    scanf("%d",&T);
    int kase=1;
    while(T--){
        printf("Case #%d:",kase++);
        init();
        solve();
        printf("\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值