总时间限制: 1000ms 内存限制: 65536kB
描述
为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。一共有n张地毯,编号从1到n。现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号。注意:在矩形地毯边界和四个顶点上的点也算被地毯覆盖。
输入输出样例1说明:如下图,1号地毯用实线表示,2号地毯用虚线表示,3号用双实线表示,覆盖点(2,2)的最上面一张地毯是3号地毯。
输入输出样例2说明:如下图,1号地毯用实线表示,2号地毯用虚线表示,3号用双实线表示,覆盖点(4,5)的最上面一张地毯是3号地毯。
输入
输入共n+2行。
第一行,一个整数n,表示总共有n张地毯。
接下来的n行中,第i+1行表示编号i的地毯的信息,包含四个正整数a,b,g,k,每两个整数之间用一个空格隔开,分别表示铺设地毯的左下角的坐标(a,b)以及地毯在x轴和y轴方向的长度。
第n+2行包含两个正整数x和y,表示所求的地面的点的坐标(x,y)。
对于30%的数据,有n≤2;
对于50%的数据,0≤a, b, g, k≤100;
对于100%的数据,有0≤n≤10,000,0≤a, b, g, k≤100,000。
输出
输出共1行,一个整数,表示所求的地毯的编号;若此处没有被地毯覆盖则输出-1。
样例输入
样例 #1: 3 1 0 2 3 0 2 3 3 2 1 3 3 2 2 样例 #2: 3 1 0 2 3 0 2 3 3 2 1 3 3 4 5
样例输出
样例 #1: 3 样例 #2: -1
【通过50%数据的解题思路】
直观的方法来解决地毯问题,其主要思路可以分为以下几个步骤:
-
初始化二维数组:创建一个二维数组
mat
,其大小足以覆盖题目给定的坐标范围,这里是101x101
(因为坐标范围是从0到100)。初始化这个数组的所有元素为-1
,表示初始时没有任何地毯覆盖对应的点。 -
读取地毯信息并更新数组:程序读取每张地毯的信息,包括地毯左下角的坐标
(a, b)
以及地毯在x
轴和y
轴方向的长度(g, k)
。对于每张地毯,程序遍历从(a, b)
开始,到(a+g, b+k)
结束的所有点,更新这些点在mat
数组中的值为当前地毯的编号。这一步骤确保了如果多张地毯覆盖同一个点,数组中存储的将是最后一张(即编号最大的)地毯的编号,因为它们是按照输入顺序,也就是铺设顺序来处理的。 -
查询特定点被哪张地毯覆盖:最后,程序读取要查询的点的坐标
(x, y)
,然后直接从mat
数组中获取该坐标对应的值,这个值就是覆盖该点的最上层地毯的编号。如果这个值是-1
,则表示该点没有被任何地毯覆盖。
关键点:
-
二维数组作为地图:使用二维数组来模拟整个区域,数组的每个元素代表对应坐标点上的地毯编号。这种方法允许我们直观地“绘制”每张地毯在区域中的位置。
-
更新逻辑:当铺设一张新地毯时,通过更新数组中的值来“覆盖”之前的地毯。由于地毯是按照编号顺序铺设的,后铺设的地毯会覆盖之前的地毯,因此数组总是反映最上层地毯的状态。
-
查询操作简化:一旦所有地毯信息都通过更新数组的方式被处理,查询某个点被哪张地毯覆盖变得非常简单快速,只需一次数组访问操作。
这个方法在处理较小数据范围时非常高效,但需要注意的是,当地毯的数量或坐标范围变大时,直接使用二维数组可能会导致内存使用量过大。因此,这种方法适用于题目中给定的较小数据范围的情况。
【代码实现】
#include <iostream>
using namespace std;
const int MAX_SIZE = 1001; // 坐标范围加1,因为坐标可以从0开始到100
int mat[MAX_SIZE][MAX_SIZE]; // 创建一个足够大的数组
int main() {
int n;
cin >> n;
// 初始化mat数组为-1,表示初始时没有地毯覆盖任何点
for (int i = 0; i < MAX_SIZE; ++i) {
for (int j = 0; j < MAX_SIZE; ++j) {
mat[i][j] = -1;
}
}
for (int i = 0; i < n; ++i) {
int a, b, g, k;
cin >> a >> b >> g >> k;
for (int x = a; x < a + g && x < MAX_SIZE; ++x) {
for (int y = b; y < b + k && y < MAX_SIZE; ++y) {
mat[x][y] = i + 1; // 使用地毯编号更新覆盖点,编号从1开始
}
}
}
int x, y;
cin >> x >> y;
cout << mat[x][y] << endl; // 直接输出对应坐标的地毯编号
return 0;
}
【通过100%数据的解题思路】
解题思路
-
读取输入数据:根据输入格式读取地毯数量、每张地毯的信息,以及查询点的坐标。
-
判断点是否被地毯覆盖:对于每一张地毯,判断给定的查询点是否落在该地毯上。可以通过比较坐标来实现:如果 a≤x≤a+g 且 b≤y≤b+k,则表示点(x,y) 被这张地毯覆盖。
-
找到最上层的地毯:由于地毯是按照编号顺序铺设的,后铺设的地毯会覆盖在先前的地毯上,所以只需要逆序遍历地毯信息数组,找到第一个覆盖该点的地毯即可。
-
输出结果:如果找到了覆盖该点的地毯,则输出该地毯的编号;否则,输出 −1。
【代码实现】
#include <iostream>
using namespace std;
struct Carp {
int a, b, g, k;
};
int main() {
int n; // 地毯数量
cin >> n;
Carp cs[n]; // 地毯信息
for (int i = 0; i < n; ++i) {
cin >> cs[i].a >> cs[i].b >> cs[i].g >> cs[i].k;
}
int x, y; // 查询点坐标
cin >> x >> y;
for (int i = n - 1; i >= 0; --i) {
if (x >= cs[i].a && x <= cs[i].a + cs[i].g && y >= cs[i].b && y <= cs[i].b + cs[i].k) {
cout << i + 1 << endl;
return 0;
}
}
cout << -1 << endl;
return 0;
}
【代码解释】定义了结构体 Carp
来存储地毯的信息。随后,程序读取地毯的数量和每张地毯的信息(左下角坐标和长度)。之后,它读取要查询的点的坐标,并从最后一张(最上面的)地毯开始向前遍历,寻找覆盖该点的地毯。如果找到了,输出该地毯的编号(由于地毯编号实际上是从1开始的,而数组索引是从0开始的,所以输出时需要加1)。如果没有找到覆盖该点的地毯,输出 -1
。