[LA 3263] 细节处理,欧拉定理
大概就是给你若干个点描述一个轨迹,这个轨迹的终点一定是和起点重合的
然后问你分成了几个平面区域
这个问题用到了欧拉定理,妙啊!
平面图的欧拉定理(不得不说欧拉牛逼啊)
E是棱的个数,其实可以理解成边,F是区域的个数,这里理解为边划分成的区域,E是顶点,也就是图论中的顶点。
至于什么是平面图,不解释了
然后代码的细节处理也要关注
1.顶点个数的考量
当然给定的这个轨迹可能有自己和自己相交,所以枚举一遍所有的线段,然后N^2求交点即可,
当然交点有可能被算了若干次,这里使用uNIQUE除去多余的就行,注意精度判断问题啊!!!
点有了,那么棱到底有多少个呢
虽然我们开始的时候搞了多余的点,但是开始一笔画的笔画数还是知道的,就是n-1
但是,这里的棱不是线段,如果三点共线当然是要算两条棱的
又到了喜闻乐见的枚举时间了,
其实也很简单,把加进来的顶点挨个询问一遍是不是在已经有的这些笔画上面,如果有的话就是一个三点共线,那么把棱数加一就行
这样子是不会重复计数的
最后解方程,小学知识咯
顺便说一下Unique的使用,要先SORT,然后就知道了
Unique使用的时候也是像SORT一样指定起止
1 const int maxn=405; 2 int n; 3 Point P[maxn],V[maxn*maxn];//V是交点的数量(交点也算顶点啊歪歪歪!) 4 //P是顶点的数量 5 int cas; 6 void solve() 7 { 8 for(int i=0;i<n;i++) 9 { 10 scanf("%lf%lf",&P[i].x,&P[i].y); 11 V[i]=P[i];//顶点肯定是交点 12 } 13 n=n-1; 14 int c=n,e=n; 15 for(int i=0;i<n;i++) 16 for(int j=i+1;j<n;j++) 17 { 18 if(SegmentProperIntersection(P[i],P[i+1],P[j],P[j+1]))//不必注意越界的问题 因为是一笔画! 19 { 20 // cout<<"EWraerdgth\n"; 21 V[c++]=GetLineIntersection(P[i],P[i+1]-P[i],P[j],P[j+1]-P[j]);//已经保证规范相交,所以不用担心,只要算出交点就是的,更不用担心线段和直线的区别 22 } 23 } 24 sort(V,V+c); 25 c=unique(V,V+c)-V; 26 for(int i=0;i<c;i++) 27 for(int j=0;j<n;j++) 28 { 29 if(OnSegment(V[i],P[j],P[j+1]))//这里的欧拉定理用的是在图上的表示,所以其实并不是所有的边数,而是棱,所以三点共线算两个! 至于为什么是棱的话,画一下图就知道了 30 e++; 31 } 32 printf("Case %d: There are %d pieces.\n",++cas,e+2-c); 33 return; 34 } 35 int main() 36 { 37 while(cin>>n) 38 { 39 if(n) 40 solve(); 41 else 42 break; 43 } 44 // while(1); 45 return 0; 46 }