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 ...
随机推荐
- fork与vfork的区别
fork()与vfock()都是创建一个进程,那他们有什么区别呢?总结有以下三点区别: 1. fork ():子进程拷贝父进程的数据段,代码段 vfork ( ):子进程与父进程共享数据段 ...
- DLL搜索路径和DLL劫持
DLL搜索路径和DLL劫持 环境:XP SP3 VS2005 作者:magictong 为什么要把DLL搜索路径(DLL ORDER)和DLL劫持(DLL Hajack)拿到一起讲呢?呵呵,其实没啥深 ...
- linux 修改命令行编码 乱码解决方案
修改/etc/default/locale命令:sudo vim /etc/default/locale1将下面这两行 LANG=zh_CN.UTF-8 LANGUAGE=zh_CN:zh 修改为: ...
- request重定向或者是response转发请求后面的代码依然执行
调用response.redirect(),或者request.getRequestDispatcher(loginAddr).forward(request,response);后,后面的代码照样执 ...
- QT中16进制字符串转汉字
最经在研究AT指令接受短信,短信是unicode编码,接受后需要根据系统的编码方案进行相关的转码比如接受到了一串字符4F60597D,它是“你好”的unicode编码,一个unicode编码占两个字节 ...
- Protected Functions 是理解OO的难点和关键
Protected Functions 是理解OO的难点和关键 private和public函数都好理解,这里就不多说了,夹在中间的prortected却有许多精妙之处,说说我的几个疑问和看法:1. ...
- java:比较对象
对象内容相等条件:1.对象类型相同(可用instanceof操作符比较)2.对象的成员变量的值完全相同 instanceof 判断对象类型 //a是否为Child对象类型 boolean b = a ...
- Java IO2:字节流
输入输出流: • 输入/输出时, 数据在通信通道中流动. 所谓“数据流(stream)”指的是所有数据通信通道之中,数据的起点和终点. 信息的通道就是一个数据流.只要是数据从一个地方“流” 到另外一个 ...
- Vim 配色设置与配色脚本语法
几个给tag加颜色的插件 https://github.com/octol/vim-cpp-enhanced-highlight:基于tag的c family语法高亮 https://github.c ...
- 用shell写个100以内的所有数字之和
#!/bin/bash i=2 while ((i<=100));do j=2 while ((j<=i/2));do if ((i%j==0));then break fi let j+ ...