计算几何学 |
坐标离散化 |
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!!
#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; }
往后看了看,全是神题。。。偶无语了。本菜太弱了,先放放,我还会回来的!!!