您的位置:首页 > 其它

UVALive 3263 二维几何基础

2017-10-12 19:24 369 查看

题意

给一笔画的N个点,问一笔画能分出多少块图形

题解

用欧拉定理,顶点数+面数-边数=2。顶点数把所有直线暴力两两相交,然后去重即可。枚举所有点,如果一个点在一条直线上,并且这个点不是端点,那么就一定是交点,这个交点把直线分成了两部分。因此可以暴力枚举点,对于每条直线,每枚举到一个交点,边数++。

注意事项

需要特别注意的是,题目的数据好像有些问题。网上大部分代码都是参考刘汝佳的蓝书,所以大部分人都没有提到线段覆盖的问题。但是实际测试发现,尽管题目明确指出了不存在线段覆盖的情况,如果特判线段覆盖(没有使用刘汝佳模板)就能AC,否则就会WA。

代码

#include<bits/stdc++.h>
#define UP(i,l,h) for(int i=l;i<h;i++)
#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)
#define W(t) while(t)
#define MEM(a,b) memset(a,b,sizeof(a))
#define LL long long
#define INF 0x3f3f3f3f
#define EPS 1e-10
#define MAXN 1010
#define MOD 1000000007
#define COUT(x) cout<<x<<endl
using namespace std;
double sqr(double x) {
return x*x;
}
int sgn(double x) {
return x<-EPS?-1:x>EPS;
}
struct Point {
double x,y;
Point(double x=0,double y=0):x(x),y(y) {}
friend Point operator + (const Point &a,const Point &b) {
return Point(a.x+b.x,a.y+b.y);
}
friend Point operator - (const Point &a,const Point &b) {
return Point(a.x-b.x,a.y-b.y);
}
friend Point operator * (const Point &a,const double &b) {
return Point(a.x*b,a.y*b);
}
friend Point operator / (const Point &a,const double &b) {
return Point(a.x/b,a.y/b);
}
friend Point operator * (const double &a,const Point &b) {
return Point(b.x*a,b.y*a);
}
double norm() {
return sqrt(sqr(x)+sqr(y));
}
friend double det(const Point &a,const Point &b) {
return a.x*b.y-a.y*b.x;
}
friend double dot(const Point &a,const Point &b) {
return a.x*b.x+a.y*b.y;
}
bool operator < (const Point b) {
return sgn(x-b.x)<0||(sgn(x-b.x)==0&&sgn(y-b.y)<0);
}
bool operator == (const Point b) {
return sgn(x-b.x)==0&&sgn(y-b.y)==0;
}
};

struct Line {
Point s,t;
Line(Point s=Point(),Point t=Point()):s(s),t(t) {}
Point vec() {
return t-s;
}
double norm() {
return vec().norm();
}
bool pointOnLine(const Point &p) {
return sgn(det(p-s,t-s))==0;
}
bool pointOnLineEx(const Point &p) {
return pointOnLine(p)&&sgn(dot(p-s,p-t))<0;
}
bool pointOnSeg(Point p) {
return pointOnLine(p)&&sgn(dot(p-s,p-t))<=0;
}
friend Point linexline(Line l1,Line l2) {
double s1=det(l1.s-l2.s,l2.vec());
double s2=det(l1.t-l2.s,l2.vec());
//        COUT(s1-s2);
return (l1.t*s1-l1.s*s2)/(s1-s2);
}
};
bool parallel(Line l1,Line l2) {
return !sgn(det(l1.vec(),l2.vec()));
}
bool sameside(Line l,Point a,Point b) {
return sgn(det(b-l.s,l.vec()))*sgn(det(a-l.s,l.vec()))>0;
}
bool isSegXSeg(Line l1,Line l2) {
if(parallel(l1,l2)) return false;
if(!sameside(l1,l2.s,l2.t)&&!sameside(l2,l1.s,l1.t)){
//        COUT("new");
return true;
}else return false;
}
Point points[510];
Point vc[25010];
int main() {
//    freopen("d:/in.txt","r",stdin);
//    freopen("d:/out1.txt","w",stdout);
int n;
int ks=1;
W(~scanf("%d",&n)) {
if(n==0) break;
MEM(points,0);
MEM(vc,0);
int lnum=0;
UP(i,0,n) {
scanf("%lf%lf",&points[i].x,&points[i].y);
//            COUT(points[i].x<<" "<<points[i].y);
}
n--;
UP(i,0,n) vc[i]=points[i];
int cnum=n;
UP(i,0,n) {
UP(j,i+1,n) {
Line l1=Line(points[i],points[i+1]);
Line l2=Line(points[j],points[j+1]);
if(isSegXSeg(l1,l2)) {
//                        COUT("good");
vc[cnum++]=linexline(l1,l2);
}
}
}
sort(vc,vc+cnum);
//        UP(i,0,cnum) COUT(vc[i].x<<" "<<vc[i].y)  ;
int v=unique(vc,vc+cnum)-vc;
//        COUT(cnum);
//        COUT(e<<" "<<v);
int e=n;
UP(i,0,v) {
UP(j,0,n) {
Line l=Line(points[j],points[j+1]);
if(l.pointOnLineEx(vc[i])) {
//                        COUT(i<<" "<<j);
e++;
}
}
}
printf("Case %d: There are %d pieces.\n",ks++,e+2-v);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: