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 ...
随机推荐
- 你不需要jQuery(二)
完全没有否定jQuery的意思,jQuery是一个神奇的.非常有用的工具,可以节省我们大量的时间. 但是,有些时候,我们只需要jQuery的一个小功能,来完成一个小任务,完全没有必要加载整个jQuer ...
- 2015-J. PUMA
描述 (题名来源:2009年校队出战合肥现场赛曾用队名) PUMA是全球著名的运动品牌,PUMA的鞋与服饰在嘻哈涂鸦文化中受到全球各地年轻人的极度欢迎,同时PUMA与adidas更是1970与1980 ...
- strip_tags() 函数剥去 HTML、XML 以及 PHP 的标签
定义和用法 strip_tags() 函数剥去 HTML.XML 以及 PHP 的标签. 语法 strip_tags(string,allow) 参数 描述 string 必需.规定要检查的字符串. ...
- codeforces #313 div1 C
同BZOJ 3782 上学路线 QAQ 还比那个简单一点 把坐标(1,1)-(n,m)平移成(0,0)-(n-1,m-1) 设dp[i]表示从(1,1)出发第一次经过障碍且到达第i个障碍的方案数 首先 ...
- codeforces #309 div1 A
先说我的解法吧 首先设f(i,j)表示选了前i个球且j种颜色都已经选完了的方案数 这显然是可以随便转移的 #include<cstdio> #include<cstring> ...
- 使用JavaMail发送邮件和接受邮件
转载:http://blog.csdn.net/zdp072/article/details/30977213 一. 为什么要学习JavaMail 为什么要学习JavaMail开发? 现在很多WEB应 ...
- 创业公司Playcafe关门大吉 创始人总结10大失败教训
导读:互联网电视游戏网站PlayCafe的创始人马克·高登森(Mark Goldenson)日前撰文,总结了自己创业失败的十个教训.以下为文章主要内容: 一年半前,我与公司联合创始人戴维·奈格(Dev ...
- C#基础精华04(文件流,文件操作,File、Directory、Path,Directory)
文件流 FileStream 可读可写 大文件 释放 StreamReader 读取 释放 StreamWriter 写入 释放 using 中释放 File 可读可写 小文件 操作文 ...
- Tomcat下server.xml中context介绍
conf/Context.xml是Tomcat公用的环境配置;若在server.xml中增加<Context path="/test" docBase="D:\te ...
- python学习笔记七--数据操作符
一.Python表达式操作符及程序: