[蓝桥杯训练] 第八届(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 <xxx>
不能通过工程设置而省略常用头文件。

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

 

2. 分析

2.1 如何计算面积

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

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

  以下是一个简单的图例:

  

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

2.2 输入坐标的两种可能

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

 

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<xEnd; i++) {
        for (int j=yBegin; j<yEnd; j++) {
            plain[i][j] = true;//暴力置位
        }
    }
}

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

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

void Print(int x1, int y1, int x2, int y2, set<string> &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<xEnd; i++) {
        for (int j=yBegin; j<yEnd; j++) {
            ostringstream s;
            string str;
            
            s.clear();
            s << i;
            str += s.str();
            str += '-';
            s.clear();
            s << j;
            str += s.str();
            st.insert(str);
        }
    }
}

 

3. 代码

 1 #include <iostream>
 2 #include <sstream>
 3 #include <fstream>
 4 #include <algorithm>
 5 #include <vector>
 6 #include <set>
 7 #include <list>
 8 #include <string>
 9 #include <map>
10 #include <cmath>
11 #include <cstring>
12 #include <cstdlib>
13 #include <windows.h>
14 
15 using namespace std;
16 
17 
18 void Print(int x1, int y1, int x2, int y2, set<string> &st);
19 #define DEBUG 1  //当你使用官方的txt测试数据时,可以将该宏置位,并在第27行更改文件名,这样就可以从txt读入测试数据,最后自行对照对应的out.txt
20 
21 
22 int main() {
23     set<string> st;
24     int n,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<n; i++) {
30         fin >> 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<n; i++) {
37         cin >> 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 <<"time:" << time <<  " ms" << endl;
44     return 0;
45 }
46 
47 void Print(int x1, int y1, int x2, int y2, set<string> &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<xEnd; i++) {
53         for (int j=yBegin; j<yEnd; j++) {
54             ostringstream s;
55             string str;
56             
57             s.clear();
58             s << i;
59             str += s.str();
60             str += '-';
61             s.clear();
62             s << j;
63             str += s.str();
64             st.insert(str);
65         }
66     }
67 }

 

 

4. 运行结果

 

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

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

posted @ 2018-03-22 16:50  In_Vincible  阅读(2230)  评论(0)    收藏  举报