信息学奥赛一本通题目解析:1863:【11NOIP提高组】铺地毯(模拟)

总时间限制: 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%数据的解题思路】

直观的方法来解决地毯问题,其主要思路可以分为以下几个步骤:

  1. 初始化二维数组:创建一个二维数组mat,其大小足以覆盖题目给定的坐标范围,这里是101x101(因为坐标范围是从0到100)。初始化这个数组的所有元素为-1,表示初始时没有任何地毯覆盖对应的点。

  2. 读取地毯信息并更新数组:程序读取每张地毯的信息,包括地毯左下角的坐标(a, b)以及地毯在x轴和y轴方向的长度(g, k)。对于每张地毯,程序遍历从(a, b)开始,到(a+g, b+k)结束的所有点,更新这些点在mat数组中的值为当前地毯的编号。这一步骤确保了如果多张地毯覆盖同一个点,数组中存储的将是最后一张(即编号最大的)地毯的编号,因为它们是按照输入顺序,也就是铺设顺序来处理的。

  3. 查询特定点被哪张地毯覆盖:最后,程序读取要查询的点的坐标(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%数据的解题思路】

解题思路

  1. 读取输入数据:根据输入格式读取地毯数量、每张地毯的信息,以及查询点的坐标。

  2. 判断点是否被地毯覆盖:对于每一张地毯,判断给定的查询点是否落在该地毯上。可以通过比较坐标来实现:如果 a≤x≤a+g 且 b≤y≤b+k,则表示点(x,y) 被这张地毯覆盖。

  3. 找到最上层的地毯:由于地毯是按照编号顺序铺设的,后铺设的地毯会覆盖在先前的地毯上,所以只需要逆序遍历地毯信息数组,找到第一个覆盖该点的地毯即可。

  4. 输出结果:如果找到了覆盖该点的地毯,则输出该地毯的编号;否则,输出 −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

  • 25
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
信息学奥赛一本通 NOIP500 第1部分》是一本参考书籍,其主要目的是为了帮助准备参加NOIP(全国青少年信息学奥林匹克的省级选拔赛)的学生进行备考。这本书的内容丰富多样,涵盖了计算机科学和编程的各个方面。 在这本书的第1部分,主要介绍了NOIP500比赛的背景和要求。它首先详细解释了NOIP500的含义和意义,以及为什么要参加这样的比赛。它还介绍了NOIP500的考试形式和内容,包括必考的算法数据结构和编程语言等。此外,它还介绍了评分标准和考试日期等重要信息。 第1部分还包括了一些备考的重要指导和技巧。它解释了如何正确准备和安排备考时间,以及如何理解和解答常见的考试题型。此外,书中还提供了一些实用的练习题和例子,帮助学生加深对知识点的理解和掌握。 这本书的语言简洁明了,结构清晰,非常适合初学者使用。它通过大量的例子和习题,帮助学生从基础知识开始逐步提高。此外,书中还附有一些重要的参考资料和学习资源,让学生能够更加全面地了解和学习计算机科学和编程。 总体而言,《信息学奥赛一本通 NOIP500 第1部分》是一本非常有价值的参考书籍,它能够为准备参加NOIP500的学生提供全面和系统的知识,帮助他们在竞赛中取得良好的成绩。对于对信息学感兴趣的学生,这本书也是一本很好的自学教材。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值