P4288 90pts求助
查看原帖
P4288 90pts求助
817668
Hukaidi8566楼主2024/4/16 14:04

18、19点WA了。

思路

不旋转点、坐标轴。

只将每个点沿 aa 的方向收缩到原来的 1/p1/p ,跑一遍最小圆覆盖。

代码

#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstdlib>
using namespace std;

const int nn=50002;
const double PAI=3.141592653589793238462643383279502884197;

int n,ra,p;
double ansx,ansy,r;
struct Node{ //点 
	double x,y;
}a[nn];

struct Line{ //直线 
	double A,B,C;
};

Line Diax(Node,double,double);
Node Jiad(Line,Line);
double Diss(Node);
Node Zngd(Node,Node);
Node Sand(Node,Node,Node);
Line Liad(Node,Node);

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y);
	scanf("%d%d",&ra,&p);//这里用ra代替题目中的a 
	
	Line fxa,fxb;//直线fxa是ra的方向 直线fxb垂直fxa于原点 
	fxa.A=-sin(ra*PAI/180);
	fxa.B=cos(ra*PAI/180);
	fxa.C=fxb.C=0;
	fxb.A=fxa.B,fxb.B=-fxa.A;
	
	for(int i=1;i<=n;i++)
	{
		Line soz=Diax(a[i],fxa.A,fxa.B);//soz是过点a[i]平行于fxa的直线 
		Node jid=Jiad(soz,fxb);//jid是soz与fxb的交点 
		
		a[i].x=(a[i].x-jid.x)/p+jid.x;
		a[i].y=(a[i].y-jid.y)/p+jid.y;
		//得到新的a[i]坐标 
	}
	
	//以下均为最小圆覆盖的部分 
	for(int i=1;i<=n;i++)
	{
		swap(a[i],a[rand()%n+1]);
	}
	
	for(int i=1;i<=n;i++)
	{
		if(Diss(a[i])>r)
		{
			ansx=a[i].x;
			ansy=a[i].y;
			r=0;
			
			for(int j=1;j<i;j++)
			{
				if(Diss(a[j])>r)
				{
					Node yxi=Zngd(a[i],a[j]);
					ansx=yxi.x;
					ansy=yxi.y;
					r=Diss(a[j]);
					
					for(int k=1;k<j;k++)
					{
						if(Diss(a[k])>r)
						{
							Node yux=Sand(a[i],a[j],a[k]);
							ansx=yux.x;
							ansy=yux.y;
							r=Diss(a[k]);
						}
					}
				}
			}
		}
	}
	
	printf("%.3lf",r);
	
	return 0;
}
Line Diax(Node t,double A,double B) //将点斜式转化为一般式
{
	Line res;
	res.A=A;
	res.B=B;
	res.C=-A*t.x-B*t.y;
	return res;
}
Node Jiad(Line l1,Line l2) //求两条直线交点坐标 
{
	Node res;
	if(l1.A==0) swap(l1,l2);
	res.y=-(l2.A*l1.C-l1.A*l2.C)/(l2.A*l1.B-l1.A*l2.B);
	res.x=-(l1.B*res.y+l1.C)/l1.A;
	return res;
}
double Diss(Node t) //求点t与原点的距离 
{
	return sqrt((t.x-ansx)*(t.x-ansx)+(t.y-ansy)*(t.y-ansy));
}
Node Zngd(Node t1,Node t2) //求两个点的中点坐标 
{
	Node res;
	res.x=(t1.x+t2.x)/2;
	res.y=(t1.y+t2.y)/2;
	return res;
}
Node Sand(Node t1,Node t2,Node t3) //求三点定圆的圆心 
{ 
	Line l12=Liad(t1,t2);
	Line l23=Liad(t2,t3);
	if(l12.A*l23.B==l12.B*l23.A) //如果三点共线 
	{
		if(t1.x!=t2.x)
		{
			if(t1.x>t2.x) swap(t1,t2);
			if(t2.x>t3.x) swap(t2,t3);
			if(t1.x>t2.x) swap(t1,t2);
		}
		else
		{
			if(t1.y>t2.y) swap(t1,t2);
			if(t2.y>t3.y) swap(t2,t3);
			if(t1.y>t2.y) swap(t1,t2);
		}
		
		return Zngd(t1,t3);
	}
	
	Node z12=Zngd(t1,t2);
	Line g1=Diax(z12,l12.B,l12.A);
	
	Node z23=Zngd(t2,t3);
	Line g2=Diax(z23,l23.B,l23.A);
	
	return Jiad(g1,g2);
}
Line Liad(Node t1,Node t2) //将两点式转化为一般式 
{
	Line res;
	res.A=t2.y-t1.y;
	res.B=t1.x-t2.x;
	res.C=-res.A*t1.x-res.B*t1.y;
	return res;
}
2024/4/16 14:04
加载中...