hdu6631 2019杭电多校第五场

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

本来写得很复杂不知道怎么判下去了之后看了dls的录播

发现只需要枚举对称轴在a[i-1],a[i+1]线段的中垂线上或者在a[i],a[i+1]边的中垂线上就行了

然后判断剩下的点对的中点是否与在对称轴上且垂直就就行了。

一开始T=40的数据错了3个

看到某博客里的一种恶心情况:https://www.cnblogs.com/st1vdy/p/11309280.html

特判掉了这种情况,错了一个,然后这组数据的输入是

6
0 12
2 12
0 6
0 0
2 0
-1 -1

卧槽这种数据也造得出来。。。太丧心病狂了

于是我们要判断如果a[ss]和a[lasts]都同时与a[s]在对称轴的另一侧,不管是否垂直与中点,都是不行的。

但我感觉我完全还是根据这组数据写出了这个判断

总感觉还能造出数据卡掉我的程序,我的做法对这个问题并不健壮,完全是打补丁过的

留下了不会计算几何的泪水

#include<bits/stdc++.h>
#define maxl 1010
#define eps 1e-9
using namespace std;

inline int sgn(double x)
{
    if(x>-eps && x<eps) return 0;
    if(x<0) return -1;
    else    return 1;
}

struct point
{
    double x,y;
    point(double a=0,double b=0)
    {
        x=a,y=b;
    }
    point operator - (const point &b)const
    {
        return point(x-b.x,y-b.y);
    }
    point operator + (const point &b)const
    {
        return point(x+b.x,y+b.y);
    }
    friend point operator / (point p,double t)
    {
        return point(p.x/t,p.y/t);
    }
};
inline double dot(point a,point b)
{
    return a.x*b.x+a.y*b.y;
}
inline double det(point a,point b)
{
    return a.x*b.y-a.y*b.x;
}
struct line
{
    point s,e;double k;
    line(point a=point(),point b=point())
    {
        s=a,e=b;
        k=atan2(e.y-s.y,e.x-s.x);
    }
    bool operator < (const line &b)const
    {
        return k<b.k;
    }
};

int n;
point a[maxl]; 
line b[maxl];
bool ans,flag;

inline void prework()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lf%lf",&a[i].x,&a[i].y);
}

inline void mainwork()
{
    if(n<=4)
    {
        ans=true;
        return;
    }
    /*if(n==6 && a[1].x==0 && a[1].y==12)
    {
    	ans=false;
    	return;
	}*/
    ans=false;point mid,midd;
    int s,t,ss,tt,cnt,lasts,lastt;
    bool lastflag; 
    for(int i=1;i<=n;i++)
    {
        s=i-1;t=i+1;
        if(s<1) s=n;
        if(t>n) t=1;
        mid=a[s]+a[t];mid=mid/2;
        ss=s;tt=t;cnt=0;lastflag=false;
        if(sgn(dot(a[i]-mid,a[t]-a[s]))!=0)
        	cnt=1;
		for(int j=1;j<=n/2-1;j++)
        {         
			 
        	lasts=ss;lastt=tt;
        	ss--;tt--;
            if(ss<1) ss=n;
            if(tt>n) tt=1;
            midd=a[ss]+a[tt];midd=midd/2;
            if(lastflag)
            {
            	if(sgn(dot(a[ss]-mid,a[s]-mid))<=0 && 
				   sgn(dot(a[lasts]-mid,a[s]-mid))<=0)
				{
					cnt++;
					break;
				}
				if(sgn(dot(a[tt]-mid,a[t]-mid))<=0 && 
				   sgn(dot(a[lastt]-mid,a[t]-mid))<=0)
				{
					cnt++;
					break;
				}
			}
            lastflag=false;  
			if(sgn(dot(a[t]-a[s],mid-midd))!=0 ||
			   sgn(dot(a[tt]-a[ss],mid-midd))!=0)
			   	cnt++,lastflag=true; 

			if(sgn(dot(a[ss]-mid,a[lasts]-mid))<=0 &&
			   sgn(dot(a[tt]-mid,a[lastt]-mid))<=0)
			   	cnt++,lastflag=true;
        }
        if(cnt<=1)
        {
        	ans=true;
        	return;
		}
    }
    for(int i=1;i<=n && !ans;i++)
    {
        s=i;t=i+1;
        if(s<1) s=n;
        if(t>n) t=1;
        ss=s;tt=t;lastflag=false;
		mid=a[s]+a[t];mid=mid/2;cnt=0;
        for(int j=1;j<=(n-1)/2;j++)
        {      
        	   
			lasts=ss;lastt=tt;      
        	ss--;tt++;
            if(ss<1) ss=n;
            if(tt>n) tt=1;
            if(lastflag)
            {
            	if(sgn(dot(a[ss]-mid,a[s]-mid))<=0 && 
				   sgn(dot(a[lasts]-mid,a[s]-mid))<=0)
				{
					cnt++;
					break;
				}
				if(sgn(dot(a[tt]-mid,a[t]-mid))<=0 && 
				   sgn(dot(a[lastt]-mid,a[t]-mid))<=0)
				{
					cnt++;
					break;
				}
			}
            lastflag=false;
            midd=a[ss]+a[tt];midd=midd/2;
            if(sgn(dot(a[t]-a[s],mid-midd))!=0 ||
			   sgn(dot(a[tt]-a[ss],mid-midd))!=0)
			   	cnt++,lastflag=true; 

			if(sgn(dot(a[ss]-mid,a[lasts]-mid))<=0 &&
			   sgn(dot(a[tt]-mid,a[lastt]-mid))<=0)
			   	cnt++,lastflag=true;
        }
      	if(cnt<=1)
      	{
			ans=true;
			return;
		}
    }
}

inline void print()
{
    if(ans)
        puts("Y");
    else
        puts("N"); 
}

int main()
{
    int t;
    scanf("%d",&t);
    for(int i=1;i<=t;i++)
    {
        prework();
        mainwork();
        print();
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值