C语言油漆面积,[蓝桥杯训练] 第八届(2017)省赛 C/C++ A组 T10 - 油漆面积

1. 题目

X星球的一批考古机器人正在一片废墟上考古。

该区域的地面坚硬如石、平整如镜。

管理人员为方便,建立了标准的直角坐标系。

每个机器人都各有特长、身怀绝技。它们感兴趣的内容也不相同。

经过各种测量,每个机器人都会报告一个或多个矩形区域,作为优先考古的区域。

矩形的表示格式为(x1,y1,x2,y2),代表矩形的两个对角点坐标。

为了醒目,总部要求对所有机器人选中的矩形区域涂黄色油漆。

小明并不需要当油漆工,只是他需要计算一下,一共要耗费多少油漆。

其实这也不难,只要算出所有矩形覆盖的区域一共有多大面积就可以了。

注意,各个矩形间可能重叠。

本题的输入为若干矩形,要求输出其覆盖的总面积。

输入格式:

第一行,一个整数n,表示有多少个矩形(1<=n<10000)

接下来的n行,每行有4个整数x1 y1 x2 y2,空格分开,表示矩形的两个对角顶点坐标。

(0<= x1,y1,x2,y2 <=10000)

输出格式:

一行一个整数,表示矩形覆盖的总面积面积。

例如,

输入:

3

1 5 10 10

3 1 20 20

2 7 15 17

程序应该输出:

340

再例如,

输入:

3

5 2 10 6

2 7 12 10

8 1 15 15

程序应该输出:

128

资源约定:

峰值内存消耗(含虚拟机) < 256M

CPU消耗 < 2000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

注意:

main函数需要返回0;

只使用ANSI C/ANSI C++ 标准;

不要调用依赖于编译环境或操作系统的特殊函数。

所有依赖的函数必须明确地在源文件中 #include

不能通过工程设置而省略常用头文件。

提交程序时,注意选择所期望的语言类型和编译器类型。

2. 分析

2.1 如何计算面积

因为坐标全是整数,这样就可以用比较简单的方法--记录坐标

但是会有TLE的问题,请自行取舍。

以下是一个简单的图例:

58885f4a8353628d26b92977447c190f.png

给出了x和y这两个对角的坐标,由于全是整数(离散),我们可以直接用两个for循环来计算面积。

2.2 输入坐标的两种可能

对角有两种情况,我们若想使用坐标法求面积,必须统一从左下角往右上角遍历,因此需要把两种类型的对角统一变成左下-右上形式的。方法如下:

74836bd42ebe4fed3f493781d615c82d.png

2.3 如何解决重叠问题

我的想法是比较简单的:建立一个10000*10000的bool型二维数组,对于每次输入的坐标,将对应区域内的bool设为true,最后厉遍统计true的数量就是面积。

void Print(int x1, int y1, int x2, int y2, bool plain[][10001]) { //第一种方法

int xBegin =min(x1,x2); //这是左下角的x

int yBegin =min(y1,y2); //这是左下角的y

int xEnd =max(x1,x2);  //这是右上角的x

int yEnd =max(y1,y2); //这是右上角的y for (int i=xBegin; i

无脑暴力,最为致命。这样做的好处是:你根本不用考虑重复的问题,因为同一个位置设置多少次也不会有任何改变,可以放心使用。当然,必须要注意的是,10000*10000的数组是会爆栈的,必须用new分配堆内存给该变量。

或者你也可以使用STL里面的set:构造一个字符串,格式为xxx-yyy,其中xxx为x坐标,yyy为y坐标,之后将其插入集合中,由于同样的坐标具有一样的形式,无法重复插入,最后只需要输出set.size()就能得到答案。(该方法不容易爆,推荐使用)

void Print(int x1, int y1, int x2, int y2, set &st) { //第二种方法,注意&不要漏了

int xBegin =min(x1,x2);

int yBegin =min(y1,y2);

int xEnd =max(x1,x2);

int yEnd =max(y1,y2); for (int i=xBegin; i

3. 代码

1 #include

2 #include

3 #include

4 #include

5 #include

6 #include

7 #include

8 #include

9 #include

10 #include

11 #include

12 #include

13 #include

14

15 using namespacestd;

16

17

18 void Print(int x1, int y1, int x2, int y2, set &st);

19 #define DEBUG 1  //当你使用官方的txt测试数据时,可以将该宏置位,并在第27行更改文件名,这样就可以从txt读入测试数据,最后自行对照对应的out.txt

20

21

22 intmain() {

23 setst;

24 intn,x1,y1,x2,y2,count; 25 long time =GetTickCount(); 26 #if DEBUG 27 ifstream fin( "in1.txt" ,ios::in); 28 fin >>n; 29 for (int i=0; i> x1 >> y1 >> x2 >>y2; 31 Print(x1,y1,x2,y2,st); 32 count =st.size(); 33 } 34 #else 35 cin >>n; 36 for (int i=0; i> x1 >> y1 >> x2 >>y2; 38 Print(x1,y1,x2,y2,st); 39 count =st.size(); 40 } 41 #endif 42 time = GetTickCount() -time;  //计算时间 43 cout << st.size() << endl < &st) { 48 int xBegin =min(x1,x2); 49 int yBegin =min(y1,y2); 50 int xEnd =max(x1,x2); 51 int yEnd =max(y1,y2); 52 for (int i=xBegin; i

4. 运行结果

805a95b09b26d35c20b2c95b5954e331.png

51e24bd19414d47f5f2ada52a51066c6.png

0485d3b4f755a00eda4884459d768c43.png

f99b124363311d56c0db4964497b7cd0.png

3811e80373284365c0372278415bdc05.png

最后两个严重TLE,尤其是是第五个测试点,不过答案至少是对了,能拿不少分。

待我更多学习之后再来优化。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值