• HDU 6631 line symmetric(计算几何)


    http://acm.hdu.edu.cn/showproblem.php?pid=6631

    题意

    给定一个多边形,问是否能在最多移动一个点的情况下使得其变成轴对称图形。

    题解

    这题我估分2800,800分给几何操作,2000分给细节.

    首先,n<=4肯定可以移动使其变成轴对称图形。

    n>=5我们可以暴力枚举所有对称轴:i和i+1连线的中垂线以及i和i+2连线的中垂线;

    时间复杂度n^2,可以接受。

    对称轴将点分成两个部分,如果两边点数相差<=1就满足条件。

    如果你觉得这就做完了那你就可以wa哭了。。。

    因为有一种情况还没有考虑:移动一个点之后引起图形自交即多边形不合法。

    如图:

    移动后合法--->

    移动后不合法--->    

    移动后不合法--->

    总结起来就是:

    如果有一组点E,F不对称,

    E点或与E直接相连的点跨过了对称轴且F点或与F直接相连的点也跨过了对称轴

    那么移动后多边形会自交。

    ok,到这里这题的细节就全部分析完毕。

    代码很好写:

      1 #define bug(x) cout<<#x<<" is "<<x<<endl
      2 #define IO std::ios::sync_with_stdio(0)
      3 #include <bits/stdc++.h>
      4 using namespace  std;
      5 #define ll long long
      6 #define mk make_pair
      7 const int N=2e3+5;
      8 const double eps=1e-6;
      9 struct Point{
     10     double x,y;
     11     Point(double x=0,double y=0):x(x),y(y){};
     12 };
     13 typedef Point Vector;
     14 int dcmp(double x){
     15     if(fabs(x)<eps)return 0;
     16     return x<0?-1:1;
     17 }
     18 Vector operator +(Vector A,Vector B){return Vector(A.x+B.x,A.y+B.y);}
     19 Vector operator -(Vector A,Vector B){return Vector(A.x-B.x,A.y-B.y);}
     20 Vector operator *(Vector A,double B){return Vector(A.x*B,A.y*B);}
     21 Vector operator /(Vector A,double B){return Vector(A.x/B,A.y/B);}
     22 bool operator<(const Point&a,const Point&b){return a.x<b.x||(a.x==b.x&&a.y<b.y);}
     23 bool operator == (const Point &a,const Point &b){return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;}
     24 double Dot(Vector A,Vector B){return A.x*B.x+A.y*B.y;}
     25 double Cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}
     26 Point p[N],a,b,A,B,m,m2,m3,p1,np;
     27 int T,n;
     28 int judge(int j, int k, Point m, Point m2) {
     29     int flag1=0,flag2=0;
     30     Vector v1=m2-m;
     31     Vector v2=p[j]-m;
     32     Vector v3,v4;
     33     if(Cross(v1,v2)){
     34         int l=j-1,r=j+1;
     35         if(l<1)l+=n;
     36         if(r>n)r-=n;
     37         v4=p[l]-m;
     38         v3=p[r]-m;
     39         if(Cross(v1,v4)*Cross(v1,v3)<0)flag1=1;
     40         if(Cross(v1,v2)*Cross(v1,v3)<0)flag1=1;
     41     }
     42     else flag1=1;
     43     v2=p[k]-m;
     44     if(Cross(v1,v2)){
     45         int l=k-1,r=k+1;
     46         /*if(l<1)l+=n;
     47         if(r>n)r-=n;*///这里加上会wa,玄学
     48         v4=p[l]-m;
     49         v3=p[r]-m;
     50         if(Cross(v1,v4)*Cross(v1,v3)<0)flag2=1;
     51         if(Cross(v1,v2)*Cross(v1,v4)<0)flag2=1;
     52     }
     53     else flag2=1;
     54     if(flag1&&flag2)return 1;
     55     return 0;
     56 }
     57 int check1(){
     58     for(int i=1;i<=n;i++){
     59         int g=0;
     60         A=p[i],B=p[i%n+1];
     61         m.x=(A.x+B.x)/2;
     62         m.y=(A.y+B.y)/2;
     63         m2.x=m.x+m.y-A.y;
     64         m2.y=m.y+A.x-m.x;
     65 
     66         if(n%2){
     67             p1=p[(i+n/2)%n+1];
     68             Vector v1=m2-m;
     69             Vector v2=p1-m;
     70             if(Cross(v1,v2))g++;
     71         }
     72         int t=n/2-1;
     73         int j=i-1,k=i+2;
     74         while(t--){
     75             if(j<1)j+=n;
     76             if(k>n)k-=n;
     77             m3.x=(p[j].x+p[k].x)/2;
     78             m3.y=(p[j].y+p[k].y)/2;
     79             Vector AB=B-A;
     80             Vector v1=m3-m;
     81             Vector v2=p[k]-p[j];
     82             if(Dot(AB,v1)!=0||Dot(v1,v2)!=0){
     83                 g++;
     84                 g+=judge(j,k,m,m2);
     85             }
     86             j--;
     87             k++;
     88         }
     89         if(g<=1)return 1;
     90     }
     91     return 0;
     92 }
     93 int check2() {
     94     for(int i=1;i<=n;i++){
     95         int g=0;
     96         A=p[i],B=p[(i+1)%n+1];
     97         m.x=(A.x+B.x)/2;
     98         m.y=(A.y+B.y)/2;
     99         m2.x=m.x+m.y-A.y;
    100         m2.y=m.y+A.x-m.x;
    101         p1=p[i%n+1];
    102         Vector v1=m2-m;
    103         Vector v2=m2-p1;
    104         if(Cross(v1,v2))g++;
    105         if(n%2==0){
    106             p1=p[(i+n/2)%n+1];
    107             v1=m2-m;
    108             v2=m2-p1;
    109             if(Cross(v1,v2))g++;
    110         }
    111         int j=i-1,k=i+3;
    112 
    113         int t=n/2-1;
    114         while(t--){
    115             if(j<1)j+=n;
    116             if(k>n)k-=n;
    117             m3.x=(p[j].x+p[k].x)/2;
    118             m3.y=(p[j].y+p[k].y)/2;
    119             Vector AB=B-A;
    120             Vector v1=m3-m;
    121             Vector v2=p[k]-p[j];
    122             if(Dot(AB,v1)!=0||Dot(v1,v2)!=0){
    123                 g++;
    124                 g+=judge(j,k,m,m2);
    125             }
    126             j--;
    127             k++;        
    128         }
    129         if(g<=1)return 1;
    130     }
    131     return 0;
    132 }
    133 int main(){
    134     scanf("%d",&T);
    135     while(T--){
    136         scanf("%d",&n);
    137         for(int i=0;i<=1000;i++)p[i]=np;
    138         for(int i=1;i<=n;i++){
    139             scanf("%lf%lf",&p[i].x,&p[i].y);
    140         }
    141         if(n<=4){
    142             printf("Y
    ");
    143             continue;
    144         }
    145         if(check1())printf("Y
    ");
    146         else if(check2())printf("Y
    ");
    147         else printf("N
    ");
    148     }
    149 }
  • 相关阅读:
    复合文字(C99)
    复浮点数(C99)
    字符串的数组形式与指针形式
    《设计模式之禅》学习笔记(十)
    旧关键字的新位置(C99)
    C的存储类、链接和内存管理
    scanf( )函数的格式化输入
    《设计模式之禅》学习笔记(十三)
    yum软件包管理器
    《设计模式之禅》学习笔记(十五)
  • 原文地址:https://www.cnblogs.com/ccsu-kid/p/11333753.html
Copyright © 2020-2023  润新知