【计算几何】FZU Problem 2270 Two Triangles

http://acm.fzu.edu.cn/problem.php?pid=2270

【题意】

给定6到10个点,从中选出6个不同的点组成两个三角形,使其中一个三角形可以通过另一个三角形平移和旋转得到。问有多少种不同的三角形选法?

【思路】

  • 全等
  • 排除对称

【Accepted】

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<string>
  5 #include<cmath>
  6 #include<algorithm>
  7 #include<queue>
  8 using namespace std;
  9 
 10 int n;
 11 const double eps=1e-6;
 12 struct Point
 13 {
 14     int x;
 15     int y;
 16     Point(){}
 17     Point(int _x,int _y):x(_x),y(_y){}
 18     Point operator-(const Point &b)const
 19     {
 20         return Point(x-b.x,y-b.y);
 21     }
 22     int operator^(const Point &b)const
 23     {
 24         return x*b.y-y*b.x;
 25     }
 26     int operator*(const Point &b)const 
 27     {
 28         return x*b.x+y*b.y;
 29     }
 30 }p[12];
 31 bool v[11][11][11][11][11][11];
 32 int dist(int i,int j)
 33 {
 34     return (p[i]-p[j])*(p[i]-p[j]);
 35 }
 36 int dis[12][12];
 37 bool judge(int i,int j,int k)
 38 {
 39     double x=sqrt(dist(i,j));
 40     double y=sqrt(dist(i,k));
 41     double z=sqrt(dist(j,k));
 42     double a[3]={x,y,z};
 43     sort(a,a+3);
 44     if(fabs(a[0]+a[1]-a[2])<=eps)
 45     {
 46         return false;
 47     }
 48     return true;
 49 }
 50 
 51 bool check(int i,int j,int k,int l,int m,int o,int flag)
 52 {
 53     int a[3]={i,k,m};
 54     int b[3]={j,l,o};
 55     sort(a,a+3);
 56     sort(b,b+3);
 57     if(v[a[0]][a[1]][a[2]][b[0]][b[1]][b[2]])
 58     {
 59         return true;
 60     }
 61     if(flag)
 62     {
 63         v[a[0]][a[1]][a[2]][b[0]][b[1]][b[2]]=1;
 64     }
 65     return false;
 66 }
 67 
 68 bool rt(int i,int j,int k,int l,int m,int o)
 69 {
 70     if(((p[k]-p[i])^(p[m]-p[k]))*((p[l]-p[j])^(p[o]-p[l]))<0)//叉积的乘积大于等于0代表方向是一样的,如果方向不一样,说明是对称的 
 71     {
 72         return false;
 73     }
 74     if(((p[m]-p[k])^(p[i]-p[m]))*((p[o]-p[l])^(p[j]-p[o]))<0)
 75     {
 76         return false;
 77     }
 78     if(((p[i]-p[m])^(p[k]-p[i]))*((p[j]-p[o])^(p[l]-p[j]))<0)
 79     {
 80         return false;
 81     }
 82     return true;
 83 }
 84 int main()
 85 {
 86     int T;
 87     scanf("%d",&T);
 88     int cas=0;
 89     while(T--)
 90     {
 91         //这个数组用来去重,一定要初始化 
 92         memset(v,0,sizeof(v));
 93         int ans=0;
 94         scanf("%d",&n);
 95         for(int i=1;i<=n;i++)
 96         {
 97             scanf("%d%d",&p[i].x,&p[i].y);        
 98         }    
 99         for(int i=1;i<=n;i++)
100         {
101             for(int j=1;j<=n;j++)
102             {
103                 if(j==i) continue;
104                 for(int k=1;k<=n;k++)
105                 {
106                     if(k==i||k==j) continue;
107                     for(int l=1;l<=n;l++)
108                     {
109                         if(l==i||l==j||l==k) continue;
110                         if(dist(i,k)!=dist(j,l)) continue;
111                         //目前为止已经选出两个三角形对应相等的两条边ik和jl 
112                         for(int m=1;m<=n;m++)
113                         {
114                             if(m==i||m==j||m==k||m==l) continue;
115                             //先选出m点,排除三点共线的情况 
116                             if(!judge(i,k,m)) continue;
117                             for(int o=1;o<=n;o++)
118                             {
119                                 if(o==i||o==j||o==k||o==l||o==m) continue;
120                                 if(dist(k,m)!=dist(l,o)||dist(m,i)!=dist(o,j)) continue;
121                                 //现在已经选出两个全等的三角形 
122                                 if(check(i,j,k,l,m,o,0)) continue;
123                                 //去重,如果是重复的重新选择    
124                                 if(rt(i,j,k,l,m,o))//因为只能是平移和旋转得到,所以要排除对称这种情况 
125                                 {
126                                     ans++;
127                                     check(i,j,k,l,m,o,1);//把这种选择标记为1 
128                                 }
129                             }    
130                         }
131                     }
132                 }
133             }    
134         }
135         printf("Case %d: %d\n",++cas,ans);    
136     }    
137     return 0;
138 } 
View Code

 

posted @ 2017-07-20 11:47  shulin15  阅读(427)  评论(0编辑  收藏  举报