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,可以接受。

HDU 6631 line symmetric(计算几何)_第1张图片HDU 6631 line symmetric(计算几何)_第2张图片

 

 

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

HDU 6631 line symmetric(计算几何)_第3张图片

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

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

如图:

HDU 6631 line symmetric(计算几何)_第4张图片移动后合法--->HDU 6631 line symmetric(计算几何)_第5张图片

 

HDU 6631 line symmetric(计算几何)_第6张图片移动后不合法--->    HDU 6631 line symmetric(计算几何)_第7张图片

 

HDU 6631 line symmetric(计算几何)_第8张图片移动后不合法--->HDU 6631 line symmetric(计算几何)_第9张图片

 

总结起来就是:

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

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

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

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

代码很好写:

  1 #define bug(x) cout<<#x<<" is "<  2 #define IO std::ios::sync_with_stdio(0)
  3 #include 
  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)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.xb.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\n");
143             continue;
144         }
145         if(check1())printf("Y\n");
146         else if(check2())printf("Y\n");
147         else printf("N\n");
148     }
149 }

 

你可能感兴趣的:(HDU 6631 line symmetric(计算几何))