| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 605 人关注过本帖
标题:大家帮忙看看这acm题目
只看楼主 加入收藏
ming84772799
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2009-11-10
收藏
 问题点数:0 回复次数:2 
大家帮忙看看这acm题目
题目描述:

平面上有n个点(0<=n<=1000),每个点用一对坐标(x,y)表示。其中x,y分别为点的x轴和y轴坐标。同时约定0<=x<=10000,0<=y<=10000,且x,y为整数。

当n个点的坐标给出后,试找出一个半径最小的圆,将n个点全部包围,点可以在圆周上。

输入格式:

第一行包含一个整数m(m<=10)表示有m组测试数据。每组测试数据的第一行为一个整数n,表示当前这组测试数据包含n个点,接下来的n行中每行有两个点,表示点的坐标。

输出格式:

对于每组数据,在一行内输出三个数,分别表示圆心坐标和半径,精确到小数点后两位。

输入输出样例:

Sample input                            Output for the input
 
3
3                                         0.50 0.50 0.71
0 0
1 0
0 1

4
0 0
0 1                                       0.50 0.50 0.71
1 1
1 0

4
0 0                                       2.00 0.00 2.00
2 0
4 0
2 2



解:

一个比较直接的想法就是枚举所有点的情况,这样就可以找到最小半径的外接圆。但是这样做的时间复杂度太高,我们需要寻求其它的方法:

给定点集A,记其最小外接圆为mincircle(A),显然对A来说mincircle(A)是存在且唯一的。还要注意一些特殊情况:当A为空集时,mincircle(A)为空;当A中只有一个点时,mincircle(A)的圆心就为该点,并且半径为0;当A中只有两个点时,mincircle(A)的圆心为两点连线的中点,半径为两点距离的一半。

显然,mincircle(A)可由A上最多三点确定,也就是说存在点集合B,|B|<=3,且B包含于A,有mincircle(A)=mincircle(B)。所以如果点a不属于集合B,那么mincircle(A-{a})=mincircle(B);如果mincircle(A-{a})<> mincircle(B),那么点a一定属于集合B。

所以我们从一个空集R开始,不断向里面添加点,并维护R的外接圆最小。这样就可以得到解决该题的算法。



#include<iostream.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
#include<iomanip.h>   

#define    sqr(a)    ((a)*(a))
#define MAX 1000
#define EPS 1E-6


struct TPoint
{   
    double x,y;
}point[MAX];

struct TCircle
{   
    TPoint centre;
    double r;
}circle;

struct TTriangle
{   
    TPoint p0,p1,p2;
}circleedge;

int casenum,pointnum;

inline double distance(TPoint p1,TPoint p2)
{   
    return sqrt(sqr(p1.x-p2.x)+sqr(p1.y-p2.y));
}

inline double triangleArea(TTriangle t)
{   
    return fabs(t.p0.x*t.p1.y+t.p1.x*t.p2.y+t.p2.x*t.p0.y - t.p1.x*t.p0.y-t.p2.x*t.p1.y-t.p0.x*t.p2.y)/2;
}

inline TCircle circumcircle(TTriangle t)
{   
    TCircle temp;
    double a,b,c,c1,c2;
    double xa,ya,xb,yb,xc,yc;
    a=distance(t.p0,t.p1);
    b=distance(t.p1,t.p2);
    c=distance(t.p2,t.p0);
    temp.r=a*b*c/triangleArea(t)/4;
    xa=t.p0.x;    ya=t.p0.y;
    xb=t.p1.x;    yb=t.p1.y;
    xc=t.p2.x;    yc=t.p2.y;
    c1=(sqr(xa)+sqr(ya)-sqr(xb)-sqr(yb))/2;
    c2=(sqr(xa)+sqr(ya)-sqr(xc)-sqr(yc))/2;
    temp.centre.x=(c1*(ya-yc)-c2*(ya-yb))/((xa-xb)*(ya-yc)-(xa-xc)*(ya-yb));
    temp.centre.y=(c1*(xa-xc)-c2*(xa-xb))/((ya-yb)*(xa-xc)-(ya-yc)*(xa-xb));
    return temp;
}

inline bool  incircle(TPoint p,TCircle c)
{   
    return distance(p,c.centre)<c.r+EPS? true:false;
}


TCircle  minCircle(int pcount,TTriangle ce)
{   
    TCircle temp;
    memset(&temp,0,sizeof(temp));
    switch(pcount)
  {
    case 0:        
        temp.r=-2;   
        break;
    case 1:        
        temp.centre=ce.p0;   
        break;
    case 2:        
        temp.r=distance(ce.p0,ce.p1)/2;   
        temp.centre.x=(ce.p0.x+ce.p1.x)/2;
        temp.centre.y=(ce.p0.y+ce.p1.y)/2;
        break;
    default:   
        temp=circumcircle(ce);
        break;
    }
    return temp;
}


void caculate(int t,int ecount,TTriangle ce){
    int i;
    circle=minCircle(ecount,ce);
    if(ecount==3) return;
    for(i=0;i<t;i++){
        
        if(distance(point[i],circle.centre)>circle.r+EPS){   
            switch(ecount){
            case 0: ce.p0=point[i];    break;
            case 1: ce.p1=point[i];    break;
            case 2:    ce.p2=point[i];    break;
            }
            caculate(t-1,ecount+1,ce);
        }
    }
}


int main()
{

    int i;
    TTriangle ce;
    cin>>casenum;
    while(casenum--)
   {
        cin>>pointnum;
        for(i=0;i<pointnum;i++)
        { cin>>point[i].x>>point[i].y;}
        caculate(pointnum,0,ce);
        cout<<setprecision(2)<<circle.centre.x<<'\t'<<setprecision(2)<<circle.centre.y<<'\t'<<setprecision(2)<<circle.r<<endl;
    }
}



人家给我的代码,不是很明白下面的一段代码,谁能给我解释一下下面这一段代码?最好详细一点 特别是ecount到底是什么?if(ecount==3) return;这个return是返回什么?这句一定需要么?还有主函数中为什么要这样调用?caculate(pointnum,0,ce);请高手指点一下

void caculate(int t,int ecount,TTriangle ce){
    int i;
    circle=minCircle(ecount,ce);
    if(ecount==3) return;
    for(i=0;i<t;i++){
        
        if(distance(point[i],circle.centre)>circle.r+EPS){   
            switch(ecount){
            case 0: ce.p0=point[i];    break;
            case 1: ce.p1=point[i];    break;
            case 2:    ce.p2=point[i];    break;
            }
            caculate(t-1,ecount+1,ce);
        }
    }
}



[ 本帖最后由 ming84772799 于 2009-11-10 14:03 编辑 ]
搜索更多相关主题的帖子: acm 
2009-11-10 13:15
qlc00
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:2
帖 子:157
专家分:540
注 册:2007-11-26
收藏
得分:0 
ecout指的是点的个数,分别为0、1、2(以及三以上)。if(ecount==3) return;这个表达式表示为真。此时什么也不返回!

Anything is possible!
2009-11-10 13:43
ming84772799
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2009-11-10
收藏
得分:0 
没人会吗?
2009-11-11 12:44
快速回复:大家帮忙看看这acm题目
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.055666 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved