标签:
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 1977 | Accepted: 626 |
Description
Input
Output
Sample Input
5 0 0 0 1 1 1 1 0 0 0 7 1 1 1 5 2 1 2 5 5 1 3 5 1 1 0
Sample Output
Case 1: There are 2 pieces. Case 2: There are 5 pieces.
欧拉公式:对任意平面图,顶点数n,边数m且含有r个区域,则有 n-m+r=2.这题最难得还是判断两线段是否相交并求出相交点。
#include<cstdio> #include<cstring> #include<stdlib.h> #define inf 0xffffff #include<iostream> #include<cmath> #define NUM 22 #include <algorithm> using namespace std; const double eps=1e-6; struct point { double x,y; point(double a=0,double b=0) { x=a; y=b; } }; bool operator< (point a, point b) { return a.x<b.x||a.x==b.x&&a.y<b.y; } bool operator == (point a,point b) { return abs(a.x-b.x)<eps&&abs(a.y-b.y)<eps; } struct Lineseg { point s,e; Lineseg(point a, point b) { s=a; e=b; } }; struct Line { double a,b,c; }; bool online(Lineseg L,point p) { //判断p是否在线段L上 return abs((L.e.x-L.s.x)*(p.y-L.s.y)-(p.x-L.s.x)*(L.e.y-L.s.y))<eps&&(p.x-L.s.x)*(p.x-L.e.x)<eps&&(p.y-L.s.y)*(p.y-L.e.y)<eps; } Line Makeline(Lineseg tmp) { //线段L变成L Line L; int x1=tmp.s.x; int y1=tmp.s.y; int x2=tmp.e.x; int y2=tmp.e.y; if(y2-y1>0) { L.a=(y2-y1); L.b=(x1-x2); L.c=(x2*y1-x1*y2); } else { L.a=(y1-y2); L.b=(x2-x1); L.c=(x1*y2-x2*y1); } return L; } bool Lineinter(Line x,Line y,point &q) { //直线X,Y相交于点q double d=x.a*y.b-y.a*x.b; if(abs(d)<eps) return false; q.x=(y.c*x.b-x.c*y.b)/d; q.y=(y.a*x.c-x.a*y.c)/d; return 1; } bool Lineseginter(Lineseg aa,Lineseg bb,point &q) { //线段aa,bb如果相交则返回交点q Line a,b; a=Makeline(aa); b=Makeline(bb); if(Lineinter(a,b,q)) return online(aa,q)&&online(bb,q); else return false; } bool cmp(point a ,point b) { if(a.x==b.x) return a.y<b.y; else return a.x<b.x; } point p[96003]; point inter[98000]; int N; int main() { int m,n; int T=0; while(scanf("%d",&N),N) { m=n=0; int cnt=0; for(int i=0; i<N; i++) scanf("%lf %lf",&p[i].x,&p[i].y); for(int i=0; i<N; i++) { for(int j=0; j<N; j++) { Lineseg L1(p[i],p[(i+1)%N]),L2(p[j],p[(j+1)%N]); point q; if(Lineseginter(L1,L2,q)) inter[cnt++]=q; } } sort(inter,inter+cnt,cmp); n=unique(inter,inter+cnt)-inter;//去重复的点 for(int i=0; i<n; i++) { for(int j=0; j<N; j++) { Lineseg t(p[j],p[(j+1)%N]); if(online(t,inter[i])&&!(t.s==inter[i]))m++; } } T++; printf("Case %d: There are %d pieces.\n",T,m+2-n);//欧拉定理 } return 0; }
POJ2284 That Nice Euler Circuit (欧拉公式)(计算几何 线段相交问题)
标签:
原文地址:http://www.cnblogs.com/jianrenfang/p/5954235.html