https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1264

  看刘汝佳的训练指南过的第一道计算几何题。开始的时候看到这题就觉得这是水题,于是瞬间就把代码打出来了。不过在debug的时候,搞着搞着发现如果像我一开始的时候那样做,好多特殊情况不能正常处理,加了好多特判都还是能找出bug。最后在搞出下面那么多数据,觉得这样特判简直就是一个无底洞,根本就不能正确的得到答案。。。- - 最后在wa到忍不住的情况下,只好求助于佳哥的题解了。。

  看了一下他的代码,瞬间觉得豁然开朗,原来之前那么的多的特判都可以通过这样的方法来消除。

  简单说一下他的做法。首先,我们可以知道顶点数V+边数E-面数F=2这个基本定理。然后,这个图形的顶点数是可以在两两判相交的时候得到的,我用一个set来保存这些个数。边数是解这题的一个关键,边数至少有n-1条,这是显而易见的,然而某些边是被分割成多少段呢?这时候就需要将我们找到的点放进线段,看看有没有将一条线段分割,有的话就将总的边数加一。因为将点放进set里了,所以所有点都是唯一的。也就是不会有同一个位置的点对同一条线段分割多于一次。最后套进欧拉定理,就可以正确的把这题解决了。

代码如下:

View Code

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cmath>
  4 #include <set>
  5 #include <vector>
  6 #include <iostream>
  7 #include <algorithm>
  8
  9 using namespace std;
 10
 11 #define REP(i, n) for (int i = 0; i < (n); i++)
 12
 13 struct Point {
 14     double x, y;
 15     Point() {}
 16     Point(double x, double y) : x(x), y(y) {}
 17 } ;
 18 template<class T> T sqr(T x) { return x * x;}
 19
 20 // basic calculations
 21 typedef Point Vec;
 22 Vec operator + (Vec a, Vec b) { return Vec(a.x + b.x, a.y + b.y);}
 23 Vec operator - (Vec a, Vec b) { return Vec(a.x - b.x, a.y - b.y);}
 24 Vec operator * (Vec a, double p) { return Vec(a.x * p, a.y * p);}
 25 Vec operator / (Vec a, double p) { return Vec(a.x / p, a.y / p);}
 26
 27 const double eps = 1e-8;
 28 int sgn(double x) { return fabs(x) < eps ? 0 : (x < 0 ? -1 : 1);}
 29 bool operator < (Point a, Point b) { return a.x < b.x || (a.x == b.x && a.y < b.y);}
 30 bool operator == (Point a, Point b) { return sgn(a.x - b.x) == 0 && sgn(a.y - b.y) == 0;}
 31
 32 double dotDet(Vec a, Vec b) { return a.x * b.x + a.y * b.y;}
 33 double vecLen(Vec x) { return sqrt(sqr(x.x) + sqr(x.y));}
 34 double angle(Vec a, Vec b) { return acos(dotDet(a, b) / vecLen(a) / vecLen(b));}
 35 double crossDet(Vec a, Vec b) { return a.x * b.y - a.y * b.x;}
 36 double triArea(Point a, Point b, Point c) { return fabs(crossDet(b - a, c - a));}
 37 Vec rotate(Vec x, double rad) { return Vec(x.x * cos(rad) - x.y * sin(rad), x.x * sin(rad) + x.y * cos(rad));}
 38 Vec normal(Vec x) {
 39     double len = vecLen(x);
 40     return Vec(- x.y / len, x.x / len);
 41 }
 42
 43 struct Line {
 44     Point s, t;
 45     Line() {}
 46     Line(Point s, Point t) : s(s), t(t) {}
 47 } ;
 48 typedef Line Seg;
 49
 50 bool onSeg(Point x, Point a, Point b) { return sgn(crossDet(a - x, b - x)) == 0 && sgn(dotDet(a - x, b - x)) < 0;}
 51 bool onSeg(Point x, Seg s) { return onSeg(x, s.s, s.t);}
 52 // 0 : not intersect
 53 // 1 : proper intersect
 54 // 2 : improper intersect
 55 int segIntersect(Point a, Point c, Point b, Point d) {
 56     Vec v1 = b - a, v2 = c - b, v3 = d - c, v4 = a - d;
 57     int a_bc = sgn(crossDet(v1, v2));
 58     int b_cd = sgn(crossDet(v2, v3));
 59     int c_da = sgn(crossDet(v3, v4));
 60     int d_ab = sgn(crossDet(v4, v1));
 61     if (a_bc * c_da > 0 && b_cd * d_ab > 0) return 1;
 62     if (onSeg(b, a, c) && c_da) return 2;
 63     if (onSeg(c, b, d) && d_ab) return 2;
 64     if (onSeg(d, c, a) && a_bc) return 2;
 65     if (onSeg(a, d, b) && b_cd) return 2;
 66     return 0;
 67 }
 68 int segIntersect(Seg a, Seg b) { return segIntersect(a.s, a.t, b.s, b.t);}
 69
 70 // point of the intersection of 2 lines
 71 Point lineIntersect(Point P, Vec v, Point Q, Vec w) {
 72     Vec u = P - Q;
 73     double t = crossDet(w, u) / crossDet(v, w);
 74     return P + v * t;
 75 }
 76 Point lineIntersect(Line a, Line b) { return lineIntersect(a.s, a.t - a.s, b.s, b.t - b.s);}
 77
 78 // directed distance
 79 double pt2Line(Point x, Point a, Point b) {
 80     Vec v1 = b - a, v2 = x - a;
 81     return crossDet(v1, v2) / vecLen(v1);
 82 }
 83 double pt2Line(Point x, Line L) { return pt2Line(x, L.s, L.t);}
 84
 85 double pt2Seg(Point x, Point a, Point b) {
 86     if (a == b) return vecLen(x - a);
 87     Vec v1 = b - a, v2 = x - a, v3 = x - b;
 88     if (sgn(dotDet(v1, v2)) < 0) return vecLen(v2);
 89     if (sgn(dotDet(v1, v3)) > 0) return vecLen(v3);
 90     return fabs(crossDet(v1, v2)) / vecLen(v1);
 91 }
 92 double pt2Seg(Point x, Seg s) { return pt2Seg(x, s.s, s.t);}
 93
 94 struct Poly {
 95     vector<Point> pt;
 96     Poly() {}
 97     Poly(vector<Point> pt) : pt(pt) {}
 98     double area() {
 99         double ret = 0.0;
100         int sz = pt.size();
101         for (int i = 1; i < sz; i++) {
102             ret += crossDet(pt[i], pt[i - 1]);
103         }
104         return fabs(ret / 2.0);
105     }
106 } ;
107
108 /****************** template above *******************/
109
110 Poly poly;
111
112 int main() {
113 //    freopen("in", "r", stdin);
114     int cas = 1, n;
115     while (cin >> n && n) {
116         set<Point> pt;
117         pt.clear();
118         poly.pt.clear();
119         int ln = n - 1;
120         double x, y;
121         for (int i = 0; i < n; i++) {
122             cin >> x >> y;
123             poly.pt.push_back(Point(x, y));
124             pt.insert(Point(x, y));
125             for (int j = 1; j < i; j++) {
126                 int st = segIntersect(Line(poly.pt[i - 1], poly.pt[i]), Line(poly.pt[j - 1], poly.pt[j]));
127                 if (st == 1) {
128                     pt.insert(lineIntersect(Line(poly.pt[i - 1], poly.pt[i]), Line(poly.pt[j - 1], poly.pt[j])));
129                 }
130             }
131         }
132         for (set<Point>::iterator si = pt.begin(); si != pt.end(); si++) {
133             for (int i = 1; i < n; i++) {
134                 if (onSeg(*si, poly.pt[i - 1], poly.pt[i])) ln++;
135             }
136         }
137         cout << "Case " << cas++ << ": There are " << ln - pt.size() + 2 << " pieces." << endl;
138     }
139     return 0;
140 }

数据如下:

View Code

  1 5
  2 0 0
  3 0 1
  4 1 1
  5 1 0
  6 0 0
  7
  8 7
  9 1 1
 10 1 5
 11 2 1
 12 2 5
 13 5 1
 14 3 5
 15 1 1
 16
 17 11
 18 0 0
 19 4 0
 20 8 0
 21 8 1
 22 7 0
 23 6 1
 24 4 0
 25 3 1
 26 2 0
 27 0 1
 28 0 0
 29
 30 7
 31 0 0
 32 1 0
 33 2 0
 34 2 1
 35 1 0
 36 0 1
 37 0 0
 38
 39 12
 40 0 0
 41 1 -1
 42 2 0
 43 1 1
 44 0 0
 45 2 0
 46 2 1
 47 0 1
 48 0 0
 49 -1 -1
 50 0 -1
 51 0 0
 52
 53 11
 54 0 0
 55 4 0
 56 8 0
 57 8 1
 58 7 0
 59 6 1
 60 4 0
 61 3 1
 62 2 0
 63 0 1
 64 0 0
 65
 66 5
 67 0 0
 68 10 0
 69 5 5
 70 5 -5
 71 0 0
 72
 73 7
 74 0 0
 75 0 -1
 76 1 0
 77 -1 0
 78 1 -2
 79 1 1
 80 0 0
 81
 82 11
 83 0 0
 84 1 0
 85 1 1
 86 -1 -1
 87 0 -1
 88 0 1
 89 -1 1
 90 1 -1
 91 0 -2
 92 -2 0
 93 0 0
 94
 95 14
 96 0 0
 97 1 0
 98 1 1
 99 -1 -1
100 0 -1
101 0 1
102 -1 1
103 1 -1
104 0 -2
105 -2 0
106 0 0
107 100 101
108 99 101
109 0 0
110
111 16
112 0 0
113 1 0
114 1 1
115 -1 -1
116 0 -1
117 0 1
118 -1 1
119 1 -1
120 0 -2
121 -2 0
122 0 0
123 100 101
124 99 101
125 -99 -101
126 -100 -101
127 0 0
128
129 0

——written by Lyon

转载于:https://www.cnblogs.com/LyonLys/archive/2013/04/29/LA_3263_Lyon.html

LA 3263 That Nice Euler Circuit (2D Geometry)相关推荐

  1. UVA10735 Euler Circuit题解

    原文链接:http://www.algorithmist.com/index.php/User:Sweepline/UVa_10735.cpp AC的C++语言程序: /* UVa 10735: fi ...

  2. 欧拉路径和欧拉回路(Euler Path and Euler Circuit)解释

    欧拉路径(欧拉回路)是图论非常重要的组成部分,欧拉路径是数学家欧拉在研究著名的德国哥尼斯堡(Koenigsberg)七桥问题时发现的.这一发现直接导致了一门新的理论研究的诞生-图论问题. 欧拉路径和欧 ...

  3. UVA1342 That Nice Euler Circuit(ACM - ICPC 2004 Asia - Shanghai)(计算几何、欧拉定理)

    整理的算法模板合集: ACM模板 欧拉定理:设平面图的顶点数.边数和面数分别为V,E,F,则V+F-E=2. #include<bits/stdc++.h> using namespace ...

  4. Poj 2284 That Nice Euler Circuit

    人生第一道正儿八经的计算几何题...光消编译错误就弄了老半天,果然是够弱.. 题意大概是,给你N条线段,它们会构成一个一笔画的图形,给你先线段的顺序就是一笔画的顺序,线段可能相交但是不会重合 问你最后 ...

  5. 如何将excel表导入oracle数据库,如何将EXCEL表导入ORACLE数据库中?【转】

    来源:https://zhidao.baidu.com/question/383828330.html?qbl=relate_question_2&word=excel%20%B1%ED%CA ...

  6. 1、DirectX 系列之 Direct 2D

    Direct 2D是一个 采用立即模式 绘图的2D 图形API,也就是跟显卡驱动打交道的一个小程序,图形业务能力包括 2-D geometry, bitmaps, and text. WM_Paint ...

  7. matlab求解关键,基于遗传算法的多辆洒水车最优路径求解(其中包含MATLAB的一些关键语句说明和Floyd,Dijkstra,Euler算法).doc...

    基于遗传算法的多辆洒水车最优路径求解(其中包含MATLAB的一些关键语句说明和Floyd,Dijkstra,Euler算法) 摘要 车辆路径问题可以分为以点为服务和以边为服务两种,洒水车问题是以边为服 ...

  8. 第7期:计算几何(持续更新中......)

    // 2022/01/22更新 更新内容主要为算法竞赛入门经典--训练指南(升级版)(刘汝佳.陈锋编著)第4章几何问题 1 二维几何基础 在平面坐标系下,向量和点一样,也用两个数x,y表示.第6章介绍 ...

  9. Go语言(golang)开源项目大全

    http://www.open-open.com/lib/view/open1396063913278.html#Compression 内容目录 Astronomy 构建工具 缓存 云计算 命令行选 ...

最新文章

  1. docker-compose的安装与简单使用
  2. Android 颜色Color(转)
  3. Linux命令大全(个人整理,如不全面望谅解)
  4. 算法笔记-两数之和、三数之和、四数之和(LeetCode)
  5. java编程赋值运算符_(24)赋值运算符
  6. 私有化仓库的 GO 模块使用实践
  7. 信息学奥赛一本通 1028:字符菱形 | OpenJudge NOI 1.1 09
  8. RANSAC估计——以直线拟合为例
  9. 你们听过最感人的故事是什么?
  10. 【笔试/面试】—— 二叉树的深度和宽度
  11. 剑指 Offer II 006. 排序数组中两个数字之和
  12. 欧姆龙NJ 中大型PLC高端型搭载欧姆龙NB触摸屏
  13. 【Zeekr_Tech】TARA攻击树分析方法论
  14. 蜂鸟E203开源RISC-V开发板:蜂鸟FPGA开发板和JTAG调试器介绍
  15. html 制作人物模型,玩家制作《辐射4》人物模型图 惊艳无比让人叹服
  16. WindowsMobile6之“HTC Touch” - iphone的强大竞争对手
  17. “特质波动率之谜”(Idiosyncratic Volatility),用Python计算特质波动率
  18. 车载SOA测试利器——Parasoft SOA自动化测试方案
  19. nodemon:运行提示错误:无法加载文件 xxxx
  20. 程序员,在什么情况下加班是可接受的

热门文章

  1. webservice python开发接口_基于Python的Webservice开发(四)-泛微OA的SOAP接口
  2. python面部颜色分析_Python图像处理之颜色的定义与使用分析
  3. C语言:存储类型,内存管理
  4. 单文件图片管理php,php封装的单文件(图片)上传类完整实例
  5. can使能上拉 gpio_单片机GPIO输入电压不可过大,最好使能上拉
  6. 2.11 计算机视觉现状
  7. Sphinx sphinx_rtd_theme
  8. Pandas 文本数据方法 strip( ) lstrip( ) rstrip( )
  9. 大V诞生记 —— 谁是VMware?
  10. 解决重启VCSA 6.0提示:503 Service Unavailable错误