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 ...
随机推荐
- 双十一运维怎么过,OneAPM 帮你救火,轻松运维
一年一度的双十一来了 有人剁手买买买,有人愁眉苦脸抱着服务器哭 对,说的就是你,汪 苦逼的运维工程师双十一怎么过来的? 守着电脑看预警还是通宵加服务器扩容 还是帮女朋友守着购物车等着一键清空 或者 今 ...
- java Tomcat数据库连接池
1. 在tomcat服务器目录下面的conf中找到一个叫Context.xml的配置文件,在其中加入以下代码 <Resource name="jdbc/books" aut ...
- cf 148D 概率DP
题意:原来袋子里有w只白鼠和b只黑鼠龙和王妃轮流从袋子里抓老鼠.谁先抓到白色老师谁就赢.王妃每次抓一只老鼠,龙每次抓完一只老鼠之后会有一只老鼠跑出来.每次抓老鼠和跑出来的老鼠都是随机的.如果两个人都没 ...
- LINQ to PostgreSQL Tutorial
原文 LINQ to PostgreSQL Tutorial This tutorial guides you through the process of creating a simple app ...
- libevent入门教程
首先给出官方文档吧: http://libevent.org ,首页有个Programming with Libevent,里面是一节一节的介绍libevent,但是感觉信息量太大了,而且还是英文的- ...
- DSPLIB for C6455+CCSv3.3
问题描述: Hello everybody, I was looking for DSPLIB libraries optimized for C6455 processors. I found th ...
- 中文编码之GB2312,Big5,GBK简介
汉字编码中现在主要用到的有三类,包括GBK,GB2312和Big5. 1.GB2312 又称国标码,由国家标准总局发布,1981年5月1日实施,通行于大陆.新加坡等地也使用此编码.它是一个简化字的编码 ...
- 关于SQL Server 数据库的备份
备份 第一 :选择数据库右键任务,然后直接选择分离,再选择删除和更新上打勾,之后到sqlsever安装目录下查看,会生成xx.mdf和xx.ldf两个文件(既有表结构又有数据). 第二:可以选择备份, ...
- ubuntu12.04升级后找不到共享目录
备注:采用VMware-workstation 10 更新命令:sudo apt-get update 今天开始搭建Android开发环境,先升级系统,升级后发现windows和ubuntu共享的目录 ...
- jQgrid问题总结
最近一段时间一直在使用jqgrid这个免费的插件,网上的资料也比较多.比较全,但是这里还是整理几个自己在开发过程中遇到的小问题. 1.自动换行 一行数据过多需要自动根据内容换行时,如果遇到在表格中的汉 ...