sgu209:Areas(计算几何)
2015-09-30 13:16
369 查看
意甲冠军:
给一些直。这架飞机被分成了很多这些线性块。每个块的需求面积封闭曲线图。
分析:
①我们应要求交点22的直线;
②每行上的交点的重排序,借此来离散一整行(正反两条边);
③对于连向一个点的几条线段,对它们进行极角排序,相邻的两条线段我们给它们之间连一条边,我们脑补一下应该能够知道如何能够保证逆时针连边;
④找循环,利用叉积求面积。
ps.ps. vectorvector的调试真心不爽…
给一些直。这架飞机被分成了很多这些线性块。每个块的需求面积封闭曲线图。
分析:
①我们应要求交点22的直线;
②每行上的交点的重排序,借此来离散一整行(正反两条边);
③对于连向一个点的几条线段,对它们进行极角排序,相邻的两条线段我们给它们之间连一条边,我们脑补一下应该能够知道如何能够保证逆时针连边;
④找循环,利用叉积求面积。
ps.ps. vectorvector的调试真心不爽…
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #define pb push_back #include <utility> #define fi first #define se second #define mp make_pair #include <stack> using namespace std; const int MAXN = 100; const int MAXE = MAXN*MAXN<<1; const double eps = 1e-8; typedef double DB; int n; #define sqr(x) ((x)*(x)) struct pot { double x, y; pot(double x = 0, double y = 0):x(x), y(y){} inline double len() {return sqrt(sqr(x)+sqr(y));} inline void read() {scanf("%lf%lf", &x, &y);} inline pot unit() { double d = len(); return pot(x/d, y/d); } inline double ang() {return atan2(y, x);} }; typedef pot vec; struct Line { pot p; vec v; Line(){} Line(pot p, vec v):p(p), v(v){} }lines[MAXN]; vector<pot> points; struct Edge { int sz; int head[MAXE], to[MAXE], ne[MAXE]; Edge() { sz = 0; memset(head, -1, sizeof(head)); } inline void add(int u, int v) { to[sz] = v;ne[sz] = head[u]; head[u] = sz++; } }E; int next[MAXE]; bool vis[MAXE]; vector<DB> ans; inline int dcmp(double x) { if(fabs(x) <= eps) return 0; else return x>0?1:-1; } inline pot operator + (const vec &a, const vec &b) {return vec(a.x+b.x, a.y+b.y);} inline pot operator - (const vec &a, const vec &b) {return vec(a.x-b.x, a.y-b.y);} inline double operator * (const vec &a, const vec &b) {return a.x*b.x+a.y*b.y;} inline double operator ^ (const vec &a, const vec &b) {return a.x*b.y-a.y*b.x;} inline pot operator * (const vec &a, double k) {return vec(a.x*k, a.y*k);} inline pot operator / (const vec &a, double k) {return vec(a.x/k, a.y/k);} inline bool operator < (const vec &a, const vec &b) {return dcmp(a.x-b.x) < 0 || (dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) < 0);} inline bool operator == (const vec &a, const vec &b) {return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;} inline pot get_line_intersection(const pot &p, const vec &v, const pot &q, const vec &w) { vec u = p-q; double t = (w^u)/(v^w); return p+v*t; } inline bool parallel(const Line &a, const Line &b) {return dcmp(a.v^b.v) == 0;} inline int get_pot_id(const pot &p) {return lower_bound(points.begin(), points.end(), p)-points.begin();} inline bool cmp(DB a, DB b) {return dcmp(a-b) == 0;} inline void init() { scanf("%d", &n); for(int i = 0; i < n; ++i) { pot a, b; a.read();b.read(); lines[i] = Line(a, b-a); } for(int i = 0; i < n; ++i) for(int j = i+1; j < n; ++j) if(!parallel(lines[i], lines[j])) points.pb(get_line_intersection(lines[i].p, lines[i].v, lines[j].p, lines[j].v)); sort(points.begin(), points.end()); points.erase(unique(points.begin(), points.end()), points.end()); for(int i = 0; i < n; ++i) { vector<DB> nodes; vec d = lines[i].v.unit(); for(int j = 0; j < n; ++j) if(!parallel(lines[i], lines[j])) { pot inter = get_line_intersection(lines[i].p, lines[i].v, lines[j].p, lines[j].v); nodes.pb((inter-lines[i].p)*d); } sort(nodes.begin(), nodes.end()); nodes.erase(unique(nodes.begin(), nodes.end(), cmp), nodes.end()); for(int j = 1, sz = nodes.size(); j < sz; ++j) { int a = get_pot_id(lines[i].p+d*nodes[j]); int b = get_pot_id(lines[i].p+d*nodes[j-1]); E.add(a, b);E.add(b, a); } } memset(next, -1, sizeof(next)); for(int i = 0, sz = points.size(); i < sz; ++i) { vector<pair<DB, int> > PA; for(int j = E.head[i]; j != -1; j = E.ne[j]) PA.pb(mp((points[E.to[j]]-points[i]).ang(), j)); sort(PA.begin(), PA.end()); for(int j = 0, sz = PA.size(); j < sz; ++j) next[PA[(j+1)%sz].se^1] = PA[j].se; } } inline void work() { for(int i = 0; i < E.sz; ++i) if(!vis[i]) { stack<int> s; int j = i; do { if(!s.empty() && (s.top()^1) == j) s.pop(); else s.push(j); vis[j] = true; j = next[j]; if(j == -1) break; }while(!vis[j]); if(i == j) { DB area = 0; while(!s.empty()) { area += (points[E.to[s.top()^1]]^points[E.to[s.top()]]); s.pop(); } area *= 0.5; if(dcmp(area) > 0) ans.pb(area); } } } inline void print() { printf("%d\n", ans.size()); sort(ans.begin(), ans.end()); for(int i = 0, sz = ans.size(); i < sz; ++i) printf("%.4lf\n", ans[i]); } int main() { init(); work(); print(); return 0; }
相关文章推荐
- jquery插件pagination实现无刷新ajax分页
- 关于陌陌签名验证机制的研究
- PowerShell 变量(Variable)
- Mac下抓取iPhone数据包的方法——无需越狱
- 截屏并保存
- 使用FlowDroid生成Android应用程序的函数调用图
- 数据库规范
- 函数返回局部变量
- 6_11:strftime 打印系统时间
- Oracle多行函数/组函数
- xss攻击
- 项目四——建设双链表算法库
- LeetCode (22): Generate Parentheses
- Cassandra 常见错误索引
- Matlab中显示法线方向 display normal map in matlab
- maven install 读取jar包时出错;error in opening zip file
- Oracle Study之--Oracle 11g RAC故障(Failed to create or upgrade OLR)
- freeswitch语音信箱(Voice Mail)功能调试
- UIImageView添加边框和阴影
- WebSockets