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;
 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,v3)<0)flag2=1;
 52     }
 53     
 54     else flag2=1;
 55     if(flag1&&flag2)return 1;
 56     return 0;
 57 }
 58 int check1(){
 59     for(int i=1;i<=n;i++){
 60         int g=0;
 61         A=p[i],B=p[i%n+1];
 62         m.x=(A.x+B.x)/2;
 63         m.y=(A.y+B.y)/2;
 64         m2.x=m.x+m.y-A.y;
 65         m2.y=m.y+A.x-m.x;
 66 
 67         if(n%2){
 68             p1=p[(i+n/2)%n+1];
 69             Vector v1=m2-m;
 70             Vector v2=p1-m;
 71             if(Cross(v1,v2))g++;
 72         }
 73         int t=n/2-1;
 74         int j=i-1,k=i+2;
 75         while(t--){
 76             if(j<1)j+=n;
 77             if(k>n)k-=n;
 78             m3.x=(p[j].x+p[k].x)/2;
 79             m3.y=(p[j].y+p[k].y)/2;
 80             Vector AB=B-A;
 81             Vector v1=m3-m;
 82             Vector v2=p[k]-p[j];
 83             if(Dot(AB,v1)!=0||Dot(v1,v2)!=0){
 84                 g++;
 85                 g+=judge(j,k,m,m2);
 86             }
 87             j--;
 88             k++;
 89         }
 90         if(g<=1)return 1;
 91     }
 92     return 0;
 93 }
 94 int check2() {
 95     for(int i=1;i<=n;i++){
 96         int g=0;
 97         A=p[i],B=p[(i+1)%n+1];
 98         m.x=(A.x+B.x)/2;
 99         m.y=(A.y+B.y)/2;
100         m2.x=m.x+m.y-A.y;
101         m2.y=m.y+A.x-m.x;
102         p1=p[i%n+1];
103         Vector v1=m2-m;
104         Vector v2=m2-p1;
105         if(Cross(v1,v2))g++;
106         if(n%2==0){
107             p1=p[(i+n/2)%n+1];
108             v1=m2-m;
109             v2=m2-p1;
110             if(Cross(v1,v2))g++;
111         }
112         int j=i-1,k=i+3;
113 
114         int t=n/2-1;
115         while(t--){
116             if(j<1)j+=n;
117             if(k>n)k-=n;
118             m3.x=(p[j].x+p[k].x)/2;
119             m3.y=(p[j].y+p[k].y)/2;
120             Vector AB=B-A;
121             Vector v1=m3-m;
122             Vector v2=p[k]-p[j];
123             if(Dot(AB,v1)!=0||Dot(v1,v2)!=0){
124                 g++;
125                 g+=judge(j,k,m,m2);
126             }
127             j--;
128             k++;        
129         }
130         if(g<=1)return 1;
131     }
132     return 0;
133 }
134 int main(){
135     scanf("%d",&T);
136     while(T--){
137         scanf("%d",&n);
138         for(int i=0;i<=1000;i++)p[i]=np;
139         for(int i=1;i<=n;i++){
140             scanf("%lf%lf",&p[i].x,&p[i].y);
141         }
142         if(n<=4){
143             printf("Y\n");
144             continue;
145         }
146         if(check1())printf("Y\n");
147         else if(check2())printf("Y\n");
148         else printf("N\n");
149     }
150 }

猜你喜欢

转载自www.cnblogs.com/ccsu-kid/p/11333753.html