[cpp]找出二维圆形中相交次数最少的圆形

朋友做助教,拿来的一道题,很简单,权当结对编程的一次练习。

问题:

  定义一个类表示二维空间中的圆形。
  要求:
    1. 包括如下数据成员:圆心坐标x, y; 半径r。坐标、半径可以为任意实数。为保护数据安全,请将数据成员定义为私有的常量成员。
    2. 为圆形提供计算面积这一成员函数。
    3. 定义友元函数用以计算两个圆是否相交(包括相交于一点)。

  利用上述类定义实现如下功能:给定多个二维空间中的圆形,找出与其他圆相交最少的一个圆形。如果有多个圆形与其他圆有相同的交点数,取其中面积最小的一个。
  要求:
    1. 输入:多个圆形的给定以文件方式进行。文件的第一行为一个正整数N,表示共有N个圆;余下文件的每一行表示一个圆,共计N行,每行将包括三个实数值,分别表示圆心的横坐标、圆心的纵坐标、圆的半径。本次测试将使用多个文件,每个文件中包含一组测试。
    2. 输出:符合要求的圆的序号,圆心的横坐标、圆心的纵坐标、圆的半径

  示例:

  输入文件内容:
  3
  0 0 1
  2 0 1
  2 2 0.5

  输出:
  1 2 0 1

分析:

  懒得考虑算法了,直接上最naive的方法。

代码:

  

#include <iostream>
#include <cmath>
#include <fstream>

using namespace std;
class Circle
{
    private:
        const double coordinateX,coordinateY,radius;
        static const double PI = 3.1415926;
    public:
        Circle(double x,double y,double r):coordinateX(x),coordinateY(y),radius(r)
        {
        }
        double getArea()
        {
            return PI*radius*radius;
        }
        friend bool isIntersect(Circle &c1,Circle &c2);
        friend void printCircle(int i,Circle &c);
};
bool isIntersect(Circle &c1,Circle &c2)
{
    double pointDistance = 0.0;
    double radiusDistance = 0.0;
    pointDistance = sqrt(pow((c1.coordinateX-c2.coordinateX),2)+pow((c1.coordinateY-c2.coordinateY),2));
    radiusDistance = c1.radius+c2.radius;
    if (pointDistance <= radiusDistance)
            return true;
    else
            return false;
}
void printCircle(int i,Circle &c){
    cout<<i<<" "<<c.coordinateX<<" "<<c.coordinateY<<" "<<c.radius<<endl;
}

int main()
{
    //打开圆的数据文件,没做异常检查
    fstream fin("data.txt");
    //文件第一行,圆的个数
    int circleNumbers = 0;
    fin >> circleNumbers;
    //创建Circle类的指针数组,从文件数据中实例化
    Circle* c[circleNumbers];
    double coordinateX,coordinateY,radius;
    int i=0;
    while(fin >> coordinateX >> coordinateY >> radius){/*beautiful!*/
        c[i]=new Circle(coordinateX,coordinateY,radius);
        //教训!
        i++;
    }
    //a[]记录每个圆与其他圆的相交次数
    int a[circleNumbers];
    for(int j=0;j<circleNumbers;j++)
    {
        a[j]=0;
        for(int k=0;k<circleNumbers;k++)
        {
            if(j!=k){
                if(isIntersect(*c[j],*c[k])==true)
                {
                    a[j]++;
                }
            }
        }
    }
    //min,所有Circle中最小的相交次数
    int min=circleNumbers;
    int k=0;
    for(int j=0;j<circleNumbers;j++)
    {
        if(a[j]<min){
            min=a[j];
            k=j;
        }
        else if(a[j]==min){
            k=((*c[k]).getArea())<=((*c[j]).getArea())?j:k;
        }
    }
    printCircle(k,*c[k]);
}

总结:

  教训还真不少。

  标签“教训”:忘了i++,别看是个小问题,debug起来真要命:一直很奇怪指针数组的*c[0]总是指向最后一个数组元素,不合常理啊。弄了很久,不小心回看前头的代码,碰巧发现了i++的问题。问题出现在每次都赋值到a[0]上,那么最后一次赋值也就在a[0]上,这时,debug容易被误导成a[0]怎么总指向数组最后一位,要不是及时跳出这个思维定势,很难发现根本原因。

  标签“beautiful”:我原来用的读文件方式弱爆了,一行一行读,再对行split,才赋值,经邹大神指出,一行代码即解决。简洁多了。

下载:

  以下给出代码和测试数据的下载链接:https://files.cnblogs.com/papershop/circle.zip

 

posted on 2013-06-16 15:54  papershop  阅读(297)  评论(0编辑  收藏  举报

导航