POJ 计算几何(2)

计算几何学

坐标离散化

 poj1151

扫描线算法

poj3277,poj1177,poj1151,poj1765,poj2280,poj3004

多边形的核

poj3130,poj3335

几何工具的综合应用

poj1066,poj1819,poj2043,poj3227,poj2165,poj3429

 

 

 

 

 

 

 

 

 

 

 

 

 

poj 1151

线段树+坐标离散化;其实就是排序后重新编号~~

扫描线算法 

poj 1177 (6/25)

求相交矩形组成的新图形的周长。很早就看过这道题。昨天用了一下午加一个晚上的时间,终于把扫描线看出点东西了。嘿嘿,几个比较好的讲解:

看着个学会的,代码风格很好:http://www.cppblog.com/abilitytao/archive/2010/07/21/120927.html

这个也挺好,不过代码风格跟我的不怎么像,所以没看代码,只看的讲解:http://www.cnblogs.com/shuaiwhu/archive/2012/04/22/2464876.html

我的线段树扫描线问题模板:http://www.cnblogs.com/vongang/archive/2012/06/25/2560816.html

 

poj 3277

跟1151一样一样的,改了改过了 

 

 多边形的核

poj 3130 && 3335

我的多边形的核模板:http://www.cnblogs.com/vongang/archive/2012/06/26/2564328.html

 这两个题目一样,都很裸,前者逆时针,后者顺时针。

 

几何工具的综合应用

 

poj 1066

题意是一个100*100的正方形,加入n条线把它分割成若干小多边形。在这个正方形里有一个点S,表示这里有宝藏。问从正方形的任一条边出发,最少经过多少个多边形某边的中点到达S点。

思路:经过中点跟经过边上的其他点一样,只不过是连接线段的角度调整。不影响所求的个数。。。

所以,只需要从S到n条线的每一个端点连线。求得与其他线段最少的交点个数就是所有的经过中点的个数。。。

ps:注意这里包括非规范相交。另外,让人无比蛋疼的是n居然可以为0,此时ans = 1!!

 

View Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <ctime>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
#define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
#define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   x < y ? x : y
#define Max(x, y)   x < y ? y : x
#define E(x)    (1 << (x))

const double eps = 1e-8;
typedef long long LL;
using namespace std;

const int N = 100;
const int inf = ~0u>>2;

struct Point {
    double x;
    double y;
};

struct Line {
    Point s;
    Point e;
};

Line L[N];
Point p[N], s;

int dbcmp(double x) {
    if(x > eps) return 1;
    else if(x < -eps)   return -1;
    return 0;
}

double det(double x1, double y1, double x2, double y2) {    //求叉积
    return x1*y2 - x2*y1;
}

double cross(Point a, Point b, Point c) {    //向量ab,和向量ac
    return det(b.x - a.x, b.y - a.y, c.x - a.x, c.y - a.y);
}

double dotdet(double x1, double y1, double x2, double y2) {    //点积
    return x1*x2 + y1*y2;
}

double dot(Point a, Point b, Point c) {
    return dotdet(b.x - a.x, b.y - a.y, c.x - a.x, c.y - a.y);
}

int betweenCmp(Point a, Point b, Point c) {    //判断a是不是在bc范围内
    return dbcmp(dot(a, b, c));
}

bool segcross(Point a, Point b, Point c, Point d) {
    double s1, s2;
    int d1, d2, d3, d4;
    d1 = dbcmp(s1 = cross(a, b, c));
    d2 = dbcmp(s2 = cross(a, b, d));
    d3 = dbcmp(cross(c, d, a));
    d4 = dbcmp(cross(c, d, b));
    if((d1^d2) == -2 && (d3^d4) == -2) {    //规范相交
        return true;
    }
    //非规范相交
    if((d1 == 0 && betweenCmp(c, a, b) <= 0) ||
       (d2 == 0 && betweenCmp(d, a, b) <= 0) ||
       (d3 == 0 && betweenCmp(a, c, d) <= 0) ||
       (d4 == 0 && betweenCmp(b, c, d) <= 0))
        return true;
    return false;
}

int main() {
    freopen("data.in", "r", stdin);

    int n, i, j, m;
    scanf("%d", &n);
    REP(i, n) {
        scanf("%lf%lf%lf%lf", &L[i].s.x, &L[i].s.y, &L[i].e.x, &L[i].e.y);
        p[i*2] = L[i].s;
        p[i*2+1] = L[i].e;
    }
    scanf("%lf%lf", &s.x, &s.y);
    m = n<<1;
    int ans = inf, cnt;
    REP(i, m) {
        cnt = 0;
        REP(j, n) {
            if(segcross(s, p[i], L[j].s, L[j].e))   cnt++;
        }
        ans = min(ans, cnt);
    }
    if(n == 0)  ans = 1;
    printf("Number of doors = %d\n", ans);
    return 0;
}

 

 

往后看了看,全是神题。。。偶无语了。本菜太弱了,先放放,我还会回来的!!! 

 

 

 

 

 

posted @ 2012-06-23 20:27  AC_Von  阅读(483)  评论(0编辑  收藏  举报