zoukankan      html  css  js  c++  java
  • 关于多边形内点数问题的一些变形

    最近两次比赛出现两道相同类型的题,有人十几分钟就AC了,而有人卡了俩小时。。。反思。。

     先说hdu4353这道题,题意是要求一个从N个点1里边画出一个多边形来,然后给出M个点2。让这个(多边形的面积/多边形内点2的个数)最小。

     描述很复杂。。。但是仔细想想会发现,多边形的点越多,面积也就越大,所以,这里只能画三个点,也就是一个三角形。至于怎么求点2的个数,这是很有必要总结的,祭奠我那苦逼的俩小时吧。。。。

    先看一个图: 

    这不是立体图,仅仅是个平面图。。。

    假设sum[i][j]表示i,j这条线上方这块区域的点的数目

    可以看到三角形内点2的数目 = sum[i][j] + sum[j][k] - sum[i][k];

    其实更通用一点就是: abs(sum[i][k] - sum[i][j] - sum[j][k]);

    既然统计出这些点数来,这个问题基本就解决了。

     HDU 4353的代码:

    View Code
    const int N = 210;
    const int M = 511;
    
    struct Point {
        int x, y;
        bool operator < (const Point& cmp) const {
            return x < cmp.x;
        }
    };
    
    Point a[N], b[M];
    int sum[N][N];
    int n, m;
    
    inline int det(int x1, int y1, int x2, int y2) {
        return x1*y2 - x2*y1;
    }
    
    inline int cross(Point a, Point b, Point c) {
        return det(b.x - a.x, b.y - a.y, c.x - a.x, c.y - a.y);
    }
    
    
    int main() {
        //freopen("data.in", "r", stdin);
    
        int i, j, k, t, cas = 0, cnt;
        double ans, area;
        scanf("%d", &t);
        while(t--) {
            scanf("%d%d", &n, &m);
            REP(i, n)   scanf("%d%d", &a[i].x, &a[i].y);
            REP(i, m)   scanf("%d%d", &b[i].x, &b[i].y);
            sort(a, a + n);
    
            for(i = 0; i < n; ++i) {
                for(j = i + 1; j < n; ++j) {
                    sum[i][j] = 0;
                    for(k = 0; k < m; ++k) {
                        if(b[k].x >= a[i].x && b[k].x < a[j].x) {
                            if(cross(a[i], a[j], b[k]) > 0) sum[i][j]++;
                        }
                    }
                }
            }
            ans = -1;
            for(i = 0; i < n; ++i) {
                for(j = i + 1; j < n; ++j) {
                    for(k = j + 1; k < n; ++k) {
                        cnt = sum[i][k] - sum[i][j] - sum[j][k];
                        if(cnt == 0)    continue;
                        area = double(cross(a[i], a[j], a[k]))/2;
                        if(ans == -1 || fabs(area/cnt) < ans)    ans = fabs(area/cnt);
                    }
                }
            }
            if(ans == -1)   printf("Case #%d: -1\n", ++cas);
            else    printf("Case #%d: %.6lf\n", ++cas, ans);
        }
        return 0;
    }

      还有一个就是多校9上的1001题(HDU 4380)。比上面这个题更直白,需要统计三角形内的点数是不是奇数就可以。。。

       

  • 相关阅读:
    UVA 11997 K Smallest Sums
    POJ 1007 DNA Sorting
    POJ 3669 Meteor Shower
    POJ 2376 Cleaning Shifts
    POJ 3050 Hopscotch
    操作系统第6次实验报告:使用信号量解决进程互斥访问
    操作系统第5次实验报告:内存管理
    操作系统第4次实验报告:文件系统
    操作系统第3次实验报告:管道
    操作系统第2次实验报告:创建进程
  • 原文地址:https://www.cnblogs.com/vongang/p/2650887.html
Copyright © 2011-2022 走看看