[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