CCF刷题计划——田地丈量

田地丈量

计算机软件能力认证考试系统

本题可以学到:重合部分矩形面积求法——对角坐标法

这道题杀疯了。我还以为只是一个简单模拟,但是实际上如果用正常几何方式思考的话,有超多情况,做成分类极其麻烦。我想过用点作为分类的条件,那么情况只有三个,一个点在矩形内部,还有两个点在矩形内部,四个点都在。但是发现点作为观测点非常不可信,因为如果四个点都不在矩形内,真的就不会有交集了吗?也不是,如果划的矩形超级大,那么重合的面积就是a*b,但是如果按照我之前的思路的话,就是没有交集。

下面来说说正确思路:求重合部分矩形的对角坐标(下面定义为 lx,ly,rx,ry)。为什么要求这个呢?假设我们存在这个重合矩形,并且知道了重合部分的对角坐标,那么长和宽就可以秒出,计算面积也就水到渠成。怎么求这个呢?我们先假设存在,那么这个重合矩形的左下角,最少是(0,0),所以 lx、ly>=0吧?而最大是多少呢?因为是左下,所以相对而言是要挑最小的,可以画图,简单看出,最大是x1,y1。同理,右上角也是,最大最大是(a,b),所以 rx<=a,ry<=b。 如果不存在这个矩形呢?不妨先按上述方法试试,试了之后就爽了,因为发现如果不存在,这两个点会在同一水平线上,所以rx=lx,计算出来的面积=0,我们可以不用分类,直接用上述方法。

AC:

#include <iostream>
using namespace std;
//好妙的一道题,说实话,几何题我一直不怎么在行。这道题的灵魂在于求出两个矩形相交部分的对角坐标 
//如果相交,那当然会有这个坐标,如果不相交,那经过上述方法计算出来的坐标在一个水平线上,根据这个算出来的面积为0 
#define ll long long
int n,a,b;
ll ans=0; 

int main()
{
	cin>>n>>a>>b;
	int x1,x2,y1,y2;	// 2>1 
	int leftx,lefty,rightx,righty;	//设置相交矩形左右(其实是左下和右上)坐标 
	while(n--)
	{
		cin>>x1>>y1>>x2>>y2;
		leftx=max(0,x1);
		lefty=max(0,y1);
		rightx=min(a,x2);
		righty=min(b,y2);
		
		//如果没有交集,leftx-rightx=0 
		int w=max(0,rightx-leftx);	//右上坐标都大于左下 
		int h=max(0,righty-lefty);
		ans+=h*w;
	}
	cout<<ans;
	return 0;
 } 

### CCF CSP 田地丈量 算法 目 解思路 #### 问分析 本的核心在于计算给定矩形区域内已有的田地面积总和。由于每块田地是一个矩形区域,可以通过判断其是否与目标矩形区域相交来决定是否计入总面积。如果存在部分重叠,则需进一步裁剪并计算有效面积。 根据输入数据的特点以及约束条件[^1],可以采用几何学中的矩形交集算法解决此问。具体来说,对于每一组田地坐标 `(x1, y1)` 和 `(x2, y2)`,需要验证它们是否落在目标矩形范围内 `(0, 0)` 到 `(a, b)` 中,并计算实际覆盖的面积。 --- #### 关键概念 1. **矩形交集判定** 给定两个矩形 A 和 B 的范围分别为 `[Ax1, Ay1], [Ax2, Ay2]` 和 `[Bx1, By1], [Bx2, By2]`,则两者是否有交集可通过以下公式判断: ```plaintext max(Ax1, Bx1) ≤ min(Ax2, Bx2) 并且 max(Ay1, By1) ≤ min(Ay2, By2) ``` 如果上述不等式成立,则说明两矩形有交集;否则无交集[^3]。 2. **交集面积计算** 若两矩形确实存在交集,则交集区域的宽度 `w` 和高度 `h` 可通过如下方式求得: ```plaintext w = max(0, min(Ax2, Bx2) - max(Ax1, Bx1)) h = max(0, min(Ay2, By2) - max(Ay1, By1)) ``` 最终交集面积即为 `area = w * h`[^4]。 --- #### 实现方法 以下是基于 Python 的实现方案: ```python def calculate_area(n, a, b, fields): total_area = 0 for field in fields: x1, y1, x2, y2 = field # 计算交集区域的边界 ix1 = max(0, x1) iy1 = max(0, y1) ix2 = min(a, x2) iy2 = min(b, y2) # 判断是否存在交集 if ix1 < ix2 and iy1 < iy2: width = ix2 - ix1 height = iy2 - iy1 area = width * height total_area += area return total_area # 示例输入 n = 4 a = 10 b = 10 fields = [ (0, 0, 5, 5), (5, -2, 15, 3), (8, 8, 15, 15), (-2, 10, 3, 15) ] result = calculate_area(n, a, b, fields) print(result) # 输出应为 44 ``` --- #### 复杂度分析 - 时间复杂度:O(n),其中 n 表示田地数量。每次只需遍历一次所有田地即可完成面积统计。 - 空间复杂度:O(1),除了存储输入外无需额外空间。 --- #### 注意事项 1. 边界情况处理非常重要,例如当某块田地完全位于目标矩形外部时,不应将其面积纳入总计。 2. 测试用例设计时应注意极端情况,比如所有田地均未覆盖到目标区域的情况。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值