uva 12296 Pieces and Discs
题意:
有个矩形,左下角(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的更多相关文章
- uva 12296 Pieces and Discs (Geometry)
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
- UVA12296 Pieces and Discs
题意 PDF 分析 可以看成直线切割多边形,直接维护. 对每个多边形考虑每条边和每个点即可. 时间复杂度?不过\(n,m \leq 20\)这种数据怎么都过了.据说是\(O(n^3)\)的,而且常数也 ...
- UVa 10213 - How Many Pieces of Land ?(欧拉公式)
链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- 【分割圆】Uva 10213 - How Many Pieces of Land ?
一个椭圆上有N个点,将这n个点两两相连,问最多能将这个椭圆分成多少片. 理清思路,慢慢推. 首先我们要想到欧拉公式:V+E-F=2 其中V为图上的顶点数,E为边数,F为平面数. 计算时的可以枚举点,从 ...
- UVa 10213 (欧拉公式+Java大数) How Many Pieces of Land ?
题意: 一块圆形土地,在圆周上选n个点,然后两两连线,问把这块土地分成多少块? 分析: 首先紫书上的公式是错的,不过根据书上提供的思路很容易稍加修改得到正确答案! 然后推公式吧,这里用到平面图的欧拉公 ...
- UVA - 10213 How Many Pieces of Land?(欧拉公式 + 高精度)
圆上有n个点,位置不确定.问这些点两两连接成的线段,最多可以把圆划分成多少块平面? 欧拉公式:V-E+F = 2,V是点数,E是边数,F是面数. 答案是F=C(n,4)+C(n,2)+1,看的别人推的 ...
- UVa 10213 How Many Pieces of Land ? (计算几何+大数)欧拉定理
题意:一块圆形土地,在圆周上选n个点,然后两两连线,问把这块土地分成多少块? 析:这个题用的是欧拉公式,在平面图中,V-E+F=2,其中V是顶点数,E是边数,F是面数.对于这个题只要计算V和E就好. ...
- UVa 10213 How Many Pieces of Land ? (计算几何+大数)
题意:一块圆形土地,在圆周上选n个点,然后两两连线,问把这块土地分成多少块? 析:这个题用的是欧拉公式,在平面图中,V-E+F=2,其中V是顶点数,E是边数,F是面数.对于这个题只要计算V和E就好. ...
- uva 10755 - Garbage Heap
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
随机推荐
- google protobuf 使用示例
定义.proto接口文件 package tutorial; message Person { required ; required int32 id = ; //unique ID number ...
- centos7 下载eclipse的镜像站点
这里吐槽一下,由于两天前centos被我农崩溃了(系统更新的锅),所以所有的开发环境又得重来一次. 其实,之前去eclipse的官网下载就很慢,打开官网也很慢,然后你会发现下下来的安装程序(只有40多 ...
- Nagios监控部署(转)
转自 http://kyhack.blog.51cto.com/490370/213355 ky.blog 一.nagios简介 nagios是一款用于系统和网络监控的应用程序,它可以在 ...
- C++11新特性:自动类型推断和类型获取
声明:本文是在Alex Allain的文章http://www.cprogramming.com/c++11/c++11-auto-decltype-return-value-after-functi ...
- windows中断与共享的连接(samba)
问题:window下当成功登录到samba服务器上的共享的目录的时候,若要是再系想登录此服务器上另外一个共享目录时,会弹出登录窗口. 但是不管输入的用户名和密码对错都会提示. “不允许一个用户使用一个 ...
- [Unity菜鸟] 协程Coroutine
1.协程,即协作式程序,其思想是,一系列互相依赖的协程间依次使用CPU,每次只有一个协程工作,而其他协程处于休眠状态. unity中StartCoroutine()就是协程,协程实际上是在一个线程中, ...
- SPRING IN ACTION 第4版笔记-第九章Securing web applications-007-设置LDAP server比较密码(contextSource、root()、ldif()、)
一.LDAP server在哪 By default, Spring Security’s LDAP authentication assumes that the LDAP server is li ...
- Java IO3:字符流
字符流 字节流提供了处理任何类型输入/输出操作的功能(对于计算机而言,一切都是0 和1,只需把数据以字节形式表示就够了),但它们不可以直接操作Unicode字符,一个Unicode字符占用2个字节,而 ...
- python 包管理工具pip安装与使用
pip是python的一个包管理工具,与之类似的工具还有easy_install.根据官网的说法 如果你的python版本在Python 2 >=2.7.9 or Python 3 >=3 ...
- No ongoing transaction. Did you forget to call multi?
2016-10-21 14:41:47,551 [ERROR] [http-nio-8032-exec-2] TransactionSynchronizationUtils:171 - Transac ...