题意:

有个矩形,左下角(0,0),左上角(L,W).

思路:

除了圆盘之外,本题的输入也是个PSLG,因此可以按照前面叙述的算法求出各个区域:只需把线段视为直线,用切割凸多边形的方法 :每次读入线段,切割所有块,最终得到若干凸多边形

如何判断多边形是否与圆盘相交:如果多边形的边和圆周规范相交,圆盘和多边形一定相交,

1:即使完全没有公共点,也可以相交,互相内含 需要判断多边形是否有顶点在园内,还需要判断圆心是否在多边形内;

2.如果不规范:  a:带判断的线段在园外;

b:带判断的线段在园内即两个端点在圆上,只需要判断中点是否在园内;

 #include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<memory.h>
#include<cstdlib>
#include<vector>
#define clc(a,b) memset(a,b,sizeof(a))
#define LL long long int
#define up(i,x,y) for(i=x;i<=y;i++)
#define w(a) while(a)
const double inf=0x3f3f3f3f;
const double eps = 1e-;
const double PI = acos(-1.0);
using namespace std; double dcmp(double x)
{
if(fabs(x) < eps) return ;
else return x < ? - : ;
} struct Point
{
double x, y;
Point(double x=, double y=):x(x),y(y) { }
}; typedef Point Vector; typedef vector<Point> Polygon; Vector operator + (Vector A, Vector B)
{
return Vector(A.x+B.x, A.y+B.y);
} Vector operator - (Point A, Point B)
{
return Vector(A.x-B.x, A.y-B.y);
} Vector operator * (Vector A, double p)
{
return Vector(A.x*p, A.y*p);
} double Dot(Vector A, Vector B)
{
return A.x*B.x + A.y*B.y;
}
double Cross(Vector A, Vector B)
{
return A.x*B.y - A.y*B.x;
}
double Length2(Vector A)
{
return Dot(A, A);
} Point GetLineIntersection(Point P, Vector v, Point Q, Vector w)
{
Vector u = P-Q;
double t = Cross(w, u) / Cross(v, w);
return P+v*t;
} bool OnSegment(Point p, Point a1, Point a2)
{
return dcmp(Cross(a1-p, a2-p)) == && dcmp(Dot(a1-p, a2-p)) < ;
} // 多边形的有向面积
double PolygonArea(Polygon poly)
{
double area = ;
int n = poly.size();
for(int i = ; i < n-; i++)
area += Cross(poly[i]-poly[], poly[(i+)%n]-poly[]);
return area/;
} // cut with directed line A->B, return the left part
// may return a single point or a line segment
Polygon CutPolygon(Polygon poly, Point A, Point B)
{
Polygon newpoly;
int n = poly.size();
for(int i = ; i < n; i++)
{
Point C = poly[i];
Point D = poly[(i+)%n];
if(dcmp(Cross(B-A, C-A)) >= ) newpoly.push_back(C);
if(dcmp(Cross(B-A, C-D)) != )
{
Point ip = GetLineIntersection(A, B-A, C, D-C);
if(OnSegment(ip, C, D)) newpoly.push_back(ip);
}
}
return newpoly;
} int isPointInPolygon(Point p, Polygon v)
{
int wn = ;
int n = v.size();
for(int i = ; i < n; i++)
{
if(OnSegment(p, v[i], v[(i+)%n])) return -; // 在边界上
int k = dcmp(Cross(v[(i+)%n]-v[i], p-v[i]));
int d1 = dcmp(v[i].y - p.y);
int d2 = dcmp(v[(i+)%n].y - p.y);
if(k > && d1 <= && d2 > ) wn++;
if(k < && d2 <= && d1 > ) wn--;
}
if (wn != ) return ; // 内部
return ; // 外部
} // 点在圆心内。圆周上不算
bool isInCircle(Point p, Point center, double R)
{
return dcmp(Length2(p-center) - R*R) < ;
} // 直线AB和圆心为C,半径为r的圆的交点
// 返回交点个数,t1, t2分别为两个交点在直线方程中的参数,p1和p2为交点本身
int getLineCircleIntersection(Point A, Point B, Point C, double r, double& t1, double& t2)
{
// 初始方程:(A.x + t(B.x - A.x) - C.x)^2 + (A.y + t(B.y - A.y) - C.y)^2 = r^2
// 整理得:(at + b)^2 + (ct + d)^2 = r^2
double a = B.x - A.x;
double b = A.x - C.x;
double c = B.y - A.y;
double d = A.y - C.y;
// 展开得:(a^2 + c^2)t^2 + 2(ab + cd)t + b^2 + d^2 - r^2 = 0,即et^2 + ft + g = 0
double e = a * a + c * c;
double f = * (a * b + c * d);
double g = b * b + d * d - r * r;
double delta = f * f - * e * g; // 判别式
if(dcmp(delta) < ) return ; // 相离
if(dcmp(delta) == ) // 相切
{
t1 = t2 = -f / ( * e);
return ;
}
t1 = (-f - sqrt(delta)) / ( * e);
t2 = (-f + sqrt(delta)) / ( * e);
return ;
} // 圆和线段是否相交(相切不算)。线段不考虑端点
bool CircleIntersectSegment(Point A, Point B, Point p, double R)
{
double t1, t2;
int c = getLineCircleIntersection(A, B, p, R, t1, t2);
if(c <= ) return false;
if(dcmp(t1) > && dcmp(t1-) < ) return true; // 端点在圆上
if(dcmp(t2) > && dcmp(t2-) < ) return true;
return false;
} /////////// 题目相关
vector<Polygon> pieces, new_pieces; void cut(int x1, int y1, int x2, int y2)
{
new_pieces.clear();
for(int i = ; i < pieces.size(); i++)
{
Polygon left = CutPolygon(pieces[i], Point(x1, y1), Point(x2, y2));
Polygon right = CutPolygon(pieces[i], Point(x2, y2), Point(x1, y1));
if(left.size() >= ) new_pieces.push_back(left);
if(right.size() >= ) new_pieces.push_back(right);
}
pieces = new_pieces;
} bool DiscIntersectPolygon(Polygon poly, Point p, double R)
{
if(isPointInPolygon(p, poly) != ) return true;
if(isInCircle(poly[], p, R)) return true;
int n = poly.size();
for(int i = ; i < n; i++)
{
if(CircleIntersectSegment(poly[i], poly[(i+)%n], p, R))
{
return true; // 不考虑线段端点
}
if(isInCircle((poly[i]+poly[(i+)%n])*0.5, p, R))
{
return true; // 两个端点都在圆上
}
}
return false;
} void query(Point p, int R)
{
vector<double> ans;
for(int i = ; i < pieces.size(); i++)
{
if(DiscIntersectPolygon(pieces[i], p, R))
{
ans.push_back(fabs(PolygonArea(pieces[i])));
}
}
printf("%d", ans.size());
sort(ans.begin(), ans.end());
for(int i = ; i < ans.size(); i++)
printf(" %.2lf", ans[i]);
printf("\n");
} int main()
{
int n, m, L, W;
while(scanf("%d%d%d%d", &n, &m, &L, &W) == && n)
{
pieces.clear(); Polygon bbox;
bbox.push_back(Point(, ));
bbox.push_back(Point(L, ));
bbox.push_back(Point(L, W));
bbox.push_back(Point(, W));
pieces.push_back(bbox); for(int i = ; i < n; i++)
{
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
cut(x1, y1, x2, y2);
} for(int i = ; i < m; i++)
{
int x, y, R;
scanf("%d%d%d", &x, &y, &R);
query(Point(x, y), R);
}
printf("\n");
}
return ;
}

uva 12296 Pieces and Discs的更多相关文章

  1. uva 12296 Pieces and Discs (Geometry)

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...

  2. UVA12296 Pieces and Discs

    题意 PDF 分析 可以看成直线切割多边形,直接维护. 对每个多边形考虑每条边和每个点即可. 时间复杂度?不过\(n,m \leq 20\)这种数据怎么都过了.据说是\(O(n^3)\)的,而且常数也 ...

  3. UVa 10213 - How Many Pieces of Land ?(欧拉公式)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  4. 【分割圆】Uva 10213 - How Many Pieces of Land ?

    一个椭圆上有N个点,将这n个点两两相连,问最多能将这个椭圆分成多少片. 理清思路,慢慢推. 首先我们要想到欧拉公式:V+E-F=2 其中V为图上的顶点数,E为边数,F为平面数. 计算时的可以枚举点,从 ...

  5. UVa 10213 (欧拉公式+Java大数) How Many Pieces of Land ?

    题意: 一块圆形土地,在圆周上选n个点,然后两两连线,问把这块土地分成多少块? 分析: 首先紫书上的公式是错的,不过根据书上提供的思路很容易稍加修改得到正确答案! 然后推公式吧,这里用到平面图的欧拉公 ...

  6. UVA - 10213 How Many Pieces of Land?(欧拉公式 + 高精度)

    圆上有n个点,位置不确定.问这些点两两连接成的线段,最多可以把圆划分成多少块平面? 欧拉公式:V-E+F = 2,V是点数,E是边数,F是面数. 答案是F=C(n,4)+C(n,2)+1,看的别人推的 ...

  7. UVa 10213 How Many Pieces of Land ? (计算几何+大数)欧拉定理

    题意:一块圆形土地,在圆周上选n个点,然后两两连线,问把这块土地分成多少块? 析:这个题用的是欧拉公式,在平面图中,V-E+F=2,其中V是顶点数,E是边数,F是面数.对于这个题只要计算V和E就好. ...

  8. UVa 10213 How Many Pieces of Land ? (计算几何+大数)

    题意:一块圆形土地,在圆周上选n个点,然后两两连线,问把这块土地分成多少块? 析:这个题用的是欧拉公式,在平面图中,V-E+F=2,其中V是顶点数,E是边数,F是面数.对于这个题只要计算V和E就好. ...

  9. uva 10755 - Garbage Heap

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...

随机推荐

  1. 学点PYTHON基础的东东--数据结构,算法,设计模式---访问者模式

    说实话,感觉不是特别多,可能没遇到过多场面, 所以对应用场景没感觉吧. 反正,各种模式就是把类的实例传来传去,久而久之,产生了一些规律...:) # 轮子,引擎, 车身这些定义好了都不需要变动 cla ...

  2. hdu 4672 Present Day, Present Time 博弈论

    看了解题报告才知道怎么做!! 题意:有 N 堆石子和 M 个石子回收站,每回合操作的人可以选择一堆石子,从中拿出一些 放到石子回收站里(可以放进多个回收站,每个回收站可以使用无数次),但每个石子回收站 ...

  3. 李洪强iOS开发之 - WebViewJavascriptBridge

    李洪强iOS开发之 - WebViewJavascriptBridge 01 - JS端:   02 - iOS端 01 遵守代理协议 02 申明属性 03 开启日志 04 给哪个webview建立J ...

  4. SQLite设置主键自动增长及插入语法

    SQLite中,一个自增长字段定义为INTEGER PRIMARY KEY AUTOINCREMENT,那么在插入一个新数据时,只需要将这个字段的值指定为NULL,即可由引擎自动设定其值,引擎会设定为 ...

  5. UnsupportedClassVersionError: Bad version number in...

    在使用eclipse开发servlet可能会出现一个很麻烦事情,版本不一致错误. java.lang.UnsupportedClassVersionError: Bad version number ...

  6. 【转】Picasso – Android系统的图片下载和缓存类库

    来源:http://blog.chengyunfeng.com/?p=492 另一篇参考:http://blog.csdn.net/xu_fu/article/details/17043231 Pic ...

  7. 键盘KeyCode值列表

    event.keycode值大全1 keycode 8 = BackSpace BackSpace 2 keycode 9 = Tab Tab 3 keycode 12 = Clear 4 keyco ...

  8. 将非WPF window设为 WPF Window的Owner

    如果WPF Content是寄宿在Win32 窗体或Windows Form中,则在WPF模块中可能不会存在WPF Window(WPF模块的根可能是个UserControl).如果在WPF模块中弹出 ...

  9. Unity NGUI弧形血条的制作

    unity版本:4.6 NGUI版本:3.6. (转载请注明参考链接及作者) 参考链接:http://www.cnblogs.com/louissong/p/3841656.html,作者:博客园 L ...

  10. 需要保存数据zabbix,不需要保存数据nagios

    需要保存数据zabbix,不需要保存数据nagios cacti 有什么好用的基于Web的Linux系统监控开源工具(网管系统) 要求类似于Ubuntu的Landscape,可以记录下历史CPU数值. ...