hdu 2215(最小覆盖圆)

来源:互联网 发布:如何加盟菜鸟网络 编辑:程序博客网 时间:2024/05/22 06:35
#include<stdio.h>  //最小覆盖圆模板。#include<math.h>#define maxn 502struct ss{    double x,y;};ss a[maxn],d;double r;double dis(ss p1,ss p2){    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));}double Cross(ss p1,ss p2,ss p3)  //叉积判断是否共线{    return (p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x);}void mindis2(ss p,ss q,int n){    d.x=(p.x+q.x)/2;    d.y=(p.y+q.y)/2;    r=dis(p,q)/2;    double c1,c2,t1,t2,t3;    for(int k=1;k<=n;k++)    {        if(dis(d,a[k])<=r) continue ;        if(Cross(p,q,a[k])!=0.0)  //三点不共线。        {            c1=(p.x*p.x+p.y*p.y-q.x*q.x-q.y*q.y)/2.0;            c2=(p.x*p.x+p.y*p.y-a[k].x*a[k].x-a[k].y*a[k].y)/2.0;            d.x=(c1*(p.y-a[k].y)-c2*(p.y-q.y))/((p.x-q.x)*(p.y-a[k].y)-(p.x-a[k].x)*(p.y-q.y));            d.y=(c1*(p.x-a[k].x)-c2*(p.x-q.x))/((p.y-q.y)*(p.x-a[k].x)-(p.y-a[k].y)*(p.x-q.x));            r=dis(d,a[k]);        }        else        {            t1=dis(p,q); t2=dis(q,a[k]); t3=dis(p,a[k]);            if(t1>=t2&&t1>=t3)            { d.x=(p.x+q.x)/2.0; d.y=(p.y+q.y)/2.0; r=dis(p,q)/2.0;}            else if(t2>=t1&&t2>=t3)            { d.x=(a[k].x+q.x)/2.0; d.y=(a[k].y+q.y)/2.0; r=dis(a[k],q)/2.0;}            else            { d.x=(a[k].x+p.x)/2.0; d.y=(a[k].y+p.y)/2.0; r=dis(a[k],p)/2.0;}        }    }}void mindis1(ss pi,int n){    d.x=(pi.x+a[1].x)/2;    d.y=(pi.y+a[1].y)/2;    r=dis(pi,a[1])/2;    for(int j=2;j<=n;j++)      if(dis(d,a[j])>r)       mindis2(pi,a[j],j-1);}void init(double &res){    char ch;    int flag=0,tmp=0,n,m,num=0;    while((ch=getchar())<'0'||ch>'9')       if(ch=='-') flag=1;    for(m=0,n=0; (ch>='0'&&ch<='9')|| (ch=='.');ch=getchar())    {         if(ch=='.') { tmp=1;continue;}         if(!tmp) m=m*10+ch-'0';         if(tmp) { n=n*10+ch-'0'; num++;}    }    res=m+n*1.0/pow(10,num);    if(flag) res*=-1;}int main(){    //freopen("Input.txt","r",stdin);    int i,n;    while(scanf("%d",&n),n)    {        for(i=1;i<=n;i++)         scanf("%lf%lf",&a[i].x,&a[i].y);//init(a[i].x);init(a[i].y);输入函数。      //所有点存在数组a中。        if(n==1) {printf("0.50\n",a[1].x,a[1].y);continue ;}        r=dis(a[1],a[2])/2;        d.x=(a[1].x+a[2].x)/2;        d.y=(a[1].y+a[2].y)/2;        for(i=3;i<=n;i++)         if(dis(d,a[i])>r)          mindis1(a[i],i-1);        // printf("%.2lf %.2lf\n",d.x,d.y); //圆心坐标。        printf("%.2lf\n",r+0.5); //hdu2215 每棵树都是直径为1的,所以最后加上0.5.    }    return 0;}

hdu 3932

hdu 3007

hdu 2215

已做。

空间n个点求最小覆盖球。 看解题报告写的,还没看过模拟退火,看似很高深的东西。

代码:

#include<iostream>#include<cstdio>#include<cmath>#define MAXN 50#define eps 1e-7using namespace std;struct P{double x,y,z;}p[MAXN],s;int n;double delta,ans;double dis(P a,P b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));}void solve(){s.x=s.y=s.z=0;delta=100;ans=1e20;while(delta>eps){int d=0;for(int i=0;i<n;i++)if(dis(s,p[i])>dis(s,p[d]))d=i;double md=dis(s,p[d]);ans=min(ans,md);s.x+=(p[d].x-s.x)/md*delta;s.y+=(p[d].y-s.y)/md*delta;s.z+=(p[d].z-s.z)/md*delta;delta*=0.98;}printf("%.5f\n",ans);}void init(double &res){    char ch;    int flag=0,tmp=0,n,m,num=0;    while((ch=getchar())<'0'||ch>'9')       if(ch=='-') flag=1;    for(m=0,n=0; (ch>='0'&&ch<='9')|| (ch=='.');ch=getchar())    {         if(ch=='.') { tmp=1;continue;}         if(!tmp) m=m*10+ch-'0';         if(tmp) { n=n*10+ch-'0'; num++;}    }    res=m+n*1.0/pow(10,num);    if(flag) res*=-1;}int main(){//freopen("Input.txt","r",stdin);while(scanf("%d",&n), n){for(int i=0;i<n;i++)    {        init(p[i].x);        init(p[i].y);        init(p[i].z);    }solve();}return 0;}