• 【计算几何】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
    ",++cas,ans);    
    136     }    
    137     return 0;
    138 } 
    View Code
  • 相关阅读:
    eclipse最有用快捷键整理(转)
    Spring IOC的配置使用(转)
    char varchar varchar2 的区别 (转)
    BigDecimal用法详解(转)
    20160126--springaop
    20160125--Spring
    20150122--接口
    Servlet与JSP的区别
    练习
    151127
  • 原文地址:https://www.cnblogs.com/itcsl/p/7210407.html
Copyright © 2020-2023  润新知