题目大意:
注释代码:
/*
* Problem ID : POJ 3831 Open-air shopping malls
* Author : Lirx.t.Una
* Language : C++
* Run Time : 0 ms
* Run Memory : 232 KB
*/
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const double INF = 1E10;
const int MAXCIRN = 20;//圆的最大数量
const double PI = 3.1415926535897932;
const double ESP = 1E-8;//精度控制
struct Cir {
double x, y;//圆心坐标
double r;//半径
Cir(void) {}
Cir( double xx, double yy, double rr ) :
x(xx), y(yy), r(rr) {}
friend istream &
operator>>(istream &is, Cir &cir) {
is >> cir.x >> cir.y >> cir.r;
return is;
}
double
POW(double x) {
return x * x;
}
double
operator^(Cir &oth) {//重载计算两个圆心之间的距离
return sqrt( POW( x - oth.x ) + POW( y - oth.y ) );
}
double
operator/(Cir &oth) {//求本圆在oth圆中的楔形的面积
double a, b, c;
double ang;
double s1, s2;
a = r;
b = (*this) ^ oth;
c = oth.r;
ang = 2.0 * acos( ( POW(a) + POW(b) - POW(c) ) / ( 2.0 * a * b ) );//余弦公式求a、b之间的夹角ang
s1 = POW(a) * ang / 2.0;//求扇形面积
s2 = POW(a) * sin(ang) / 2.0;//求三角形面积
return s1 - s2;
}
double
operator*(Cir &oth) {//求重叠区域面积
return (*this) / oth + oth / (*this);
}
bool
operator>(Cir &oth) {//求两者重叠面积是否超过后者的一半
double dist;
dist = (*this) ^ oth;
//如果两圆无重叠
if ( dist - ( r + oth.r ) > ESP ) return false;
if ( fabs( r - oth.r ) - dist > ESP )//如果一个包在另一个里面
if ( r - oth.r > ESP ) return true;//前者包含后者
else return POW(r) * 2.0 - POW(oth.r) > ESP;//后者包含前者,但是需要检查前者面积是否超过后者一半
return (*this) * oth * 2.0 - POW(oth.r) * PI > ESP;//否则就是正常的相交了
}
};
int n;//圆的数量
Cir cir[MAXCIRN];//Circle
bool
check(Cir &cc) {//检查圆cc是否和其它所有圆的重叠部分超过各圆面积的一半
int i;
for ( i = 0; i < n; i++ )
if ( !( cc > cir[i] ) )
return false;
return true;
}
int
main() {
int t;//测例数
int i;//计数变量
double lft, rht, mid;//二分搜索
double ans;//最终的最小半径
scanf("%d", &t);
while ( t-- ) {
scanf("%d", &n);
for ( i = 0; i < n; i++ ) cin >> cir[i];
ans = INF;
for ( i = 0; i < n; i++ ) {//对每个位置逐个枚举
lft = 0;
rht = 50000;//二分最大断点
while ( rht - lft > 1E-6 ) {//二分精度
Cir cc( cir[i].x, cir[i].y, mid = ( lft + rht ) / 2.0);
if ( check(cc) ) rht = mid;
else lft = mid;
}
ans = min( ans, ( lft + rht ) / 2.0 );//更新每一个位置的结果对ans的改变
}
printf("%.4lf\n", ans);
}
return 0;
}
无注释代码:
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const double INF = 1E10;
const int MAXCIRN = 20;
const double PI = 3.1415926535897932;
const double ESP = 1E-8;
struct Cir {
double x, y;
double r;
Cir(void) {}
Cir( double xx, double yy, double rr ) :
x(xx), y(yy), r(rr) {}
friend istream &
operator>>(istream &is, Cir &cir) {
is >> cir.x >> cir.y >> cir.r;
return is;
}
double
POW(double x) {
return x * x;
}
double
operator^(Cir &oth) {
return sqrt( POW( x - oth.x ) + POW( y - oth.y ) );
}
double
operator/(Cir &oth) {
double a, b, c;
double ang;
double s1, s2;
a = r;
b = (*this) ^ oth;
c = oth.r;
ang = 2.0 * acos( ( POW(a) + POW(b) - POW(c) ) / ( 2.0 * a * b ) );
s1 = POW(a) * ang / 2.0;
s2 = POW(a) * sin(ang) / 2.0;
return s1 - s2;
}
double
operator*(Cir &oth) {
return (*this) / oth + oth / (*this);
}
bool
operator>(Cir &oth) {
double dist;
dist = (*this) ^ oth;
if ( dist - ( r + oth.r ) > ESP ) return false;
if ( fabs( r - oth.r ) - dist > ESP )
if ( r - oth.r > ESP ) return true;
else return POW(r) * 2.0 - POW(oth.r) > ESP;
return (*this) * oth * 2.0 - POW(oth.r) * PI > ESP;
}
};
int n;
Cir cir[MAXCIRN];
bool
check(Cir &cc) {
int i;
for ( i = 0; i < n; i++ )
if ( !( cc > cir[i] ) )
return false;
return true;
}
int
main() {
int t;
int i;
double lft, rht, mid;
double ans;
scanf("%d", &t);
while ( t-- ) {
scanf("%d", &n);
for ( i = 0; i < n; i++ ) cin >> cir[i];
ans = INF;
for ( i = 0; i < n; i++ ) {
lft = 0;
rht = 50000;
while ( rht - lft > 1E-6 ) {
Cir cc( cir[i].x, cir[i].y, mid = ( lft + rht ) / 2.0);
if ( check(cc) ) rht = mid;
else lft = mid;
}
ans = min( ans, ( lft + rht ) / 2.0 );
}
printf("%.4lf\n", ans);
}
return 0;
}
单词解释: