[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       }      

 

posted @ 2019-10-08 23:50  Amazonite  阅读(143)  评论(0编辑  收藏  举报