1 条题解

  • 0
    @ 2025-4-13 21:54:51

    题意分析

    解题思路

    1. 采用回溯法来尝试所有可能的中继站组合。

    2. 定义函数计算两个圆的重叠面积(intersectionArea):根据两圆的圆心距 d=(axbx)2+(ayby)2d = \sqrt{(a_x - b_x)^2 + (a_y - b_y)^2}与两圆半径的关系,分情况计算重叠面积。若d ≥a.r + b.r,两圆不重叠,重叠面积为(0);若d ≤ |a.r - b.r|,一个圆完全包含在另一个圆内,重叠面积为较小圆的面积;否则通过余弦定理计算圆心角,进而算出重叠面积。

    3. 定义函数计算总覆盖面积(calculateTotalArea):先将基站面积πR2{\pi R^2}加入总面积,然后对每个选中的中继站,加上其面积πR2{\pi R^2},并减去该中继站与基站以及已选中中继站之间的重叠面积。

    4. 在回溯函数(backtrack)中,对于每个候选中继站,分别考虑选和不选两种情况。选的时候,检查该中继站与已选的中继站是否不相交(通过比较圆心距与半径和),若不相交则将其加入已选集合,继续递归;不选则直接递归下一个中继站。每次递归结束后,更新最大覆盖面积。

    分析

    实现步骤

    代码实现

    #include <iostream>
    #include <iomanip>
    #include <cmath>
    #include <vector>
    using namespace std;
    
    const double PI = acos(-1.0);
    const double EPS = 1e-9;
    
    struct Station {
    	double x, y, r;
    };
    
    // 计算两个圆的重叠面积
    double intersectionArea(Station a, Station b) {
    	double d = sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
    	if (d >= a.r + b.r) return 0;
    	if (d <= fabs(a.r - b.r)) return PI * min(a.r, b.r) * min(a.r, b.r);
    	
    	double cosAlpha = (a.r * a.r + d * d - b.r * b.r) / (2 * a.r * d);
    	double alpha = acos(cosAlpha);
    	double cosBeta = (b.r * b.r + d * d - a.r * a.r) / (2 * b.r * d);
    	double beta = acos(cosBeta);
    	
    	double sectorA = a.r * a.r * alpha;
    	double triangleA = a.r * a.r * sin(alpha) * cosAlpha;
    	double sectorB = b.r * b.r * beta;
    	double triangleB = b.r * b.r * sin(beta) * cosBeta;
    	
    	return sectorA + sectorB - triangleA - triangleB;
    }
    
    // 计算当前选择的基站和中继站的总覆盖面积
    double calculateTotalArea(Station base, const vector<Station>& selected) {
    	double total = PI * base.r * base.r;
    	for (int i = 0; i < selected.size(); ++i) {
    		total += PI * selected[i].r * selected[i].r;
    		total -= intersectionArea(base, selected[i]);
    		for (int j = 0; j < i; ++j) {
    			total -= intersectionArea(selected[i], selected[j]);
    		}
    	}
    	return total;
    }
    
    // 回溯法尝试所有可能的中继站组合
    void backtrack(int index, Station base, const vector<Station>& candidates, 
    	vector<Station>& selected, double& maxArea) {
    		if (index == candidates.size()) {
    			maxArea = max(maxArea, calculateTotalArea(base, selected));
    			return;
    		}
    		
    		// 不选择当前中继站
    		backtrack(index + 1, base, candidates, selected, maxArea);
    		
    		// 检查当前中继站是否与已选的中继站不相交
    		bool canSelect = true;
    		for (const auto& s : selected) {
    			if (sqrt((s.x - candidates[index].x) * (s.x - candidates[index].x) + 
    				(s.y - candidates[index].y) * (s.y - candidates[index].y)) < 
    				s.r + candidates[index].r - EPS) {
    				canSelect = false;
    				break;
    			}
    		}
    		if (canSelect) {
    			selected.push_back(candidates[index]);
    			backtrack(index + 1, base, candidates, selected, maxArea);
    			selected.pop_back();
    		}
    	}
    
    int main() {
    	int N;
    	double x0, y0, R;
    	cin >> N >> x0 >> y0 >> R;
    	
    	Station base = {x0, y0, R};
    	vector<Station> candidates(N);
    	for (int i = 0; i < N; ++i) {
    		cin >> candidates[i].x >> candidates[i].y >> candidates[i].r;
    	}
    	
    	vector<Station> selected;
    	double maxArea = 0;
    	backtrack(0, base, candidates, selected, maxArea);
    	
    	cout << fixed << setprecision(4) << maxArea << endl;
    	
    	return 0;
    }
    

    代码说明

    1. 头文件和常量定义

      (1)包含了输入输出流()、精度设置()、数学函数()和向量容器()的头文件。

      (2)定义了常量(PI)(通过(acos(-1.0))计算圆周率)和(EPS)(用于比较浮点数时的精度误差,值为(1e - 9))。

    2. 结构体定义:Station结构体用于存储基站和中继站的信息,包括坐标(x)、(y)和半径(r)。

    3. intersectionArea函数:计算两个圆的重叠面积,根据圆心距与半径的关系分情况讨论,运用余弦定理和三角函数计算重叠部分的扇形和三角形面积,进而得到重叠面积。

    4. calculateTotalArea函数:计算当前选择的基站和中继站的总覆盖面积,先加上基站面积和各中继站面积,再减去基站与中继站、中继站之间的重叠面积。

    5. backtrack函数:回溯法的核心函数,递归地尝试所有可能的中继站组合。对于每个候选中继站,分别考虑选和不选的情况,选的时候检查是否与已选的中继站相交,若不相交则加入已选集合并继续递归,最后更新最大面积。

    6. main函数:读取输入数据,初始化基站和候选中继站信息,调用回溯函数计算最大覆盖面积,并输出结果,设置输出精度为小数点后(4)位。

    • 1

    信息

    ID
    1383
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    8
    已通过
    1
    上传者