【信息学竞赛真题! ! !】信息学竞赛人必看的「NOIP2011」铺地毯 题解(C++版)

本文介绍了NOIP2011竞赛中的一道铺地毯问题,探讨了使用二维数组和改进算法解决该问题的思路。通过对输入数据的分析和算法优化,实现了高效查询地面某点被哪张地毯覆盖。适合有一定C++基础的信息学竞赛学习者。

Hi,朋友们。又见面了。上次我们做了一道美国题,这次我们来干一道“国产”题目

(本文适合学习C++有那么一点点基础,但基础又不是特别高的朋友)

A.题目描述

题目描述

为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。一共有n 张地毯,编号从1 到n。现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号。注意:在矩形地毯边界和四个顶点上的点也算被地毯覆盖。

输入

输入共 n+2 行。
第一行,一个整数 n,表示总共有n 张地毯。
接下来的 n 行中,第i+1 行表示编号i 的地毯的信息,包含四个正整数a,b,g,k,每两个整数之间用一个空格隔开,分别表示铺设地毯的左下角的坐标(a,b)以及地毯在x轴和y 轴方向的长度。
第 n+2 行包含两个正整数x 和y,表示所求的地面的点的坐标(x,y)。

输出

输出共 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

提示

对于 30%的数据,有n≤2;
对于 50%的数据,0≤a, b, g, k≤100;
对于 100%的数据,有0≤n≤10,000,0≤a, b, g, k≤100,000。

来源
NOIP2011

B.初步分析

如果使用二维数组……

二维数组,感觉是这种题名正言顺的做法……
这是一个网格——
在这里插入图片描述
名义上二维数组是行得通的,只需要定义这么大的个数组,然后一层层往上面铺,再查询某个坐标面上的是那张地毯——

	for(int i=1;i<=n;i++){
		scanf("%d%d%d%d",&a,&b,&g,&k);
		for(int j=b;j<=b+k;j++){
			for(int l=a-g;l<=a;l++){
				p[j][l]=i;
			}
		}
	}
if(p[x][y]==0){//查看这个点最上层是哪张地毯 
		printf("-1");
	}
else
	printf("%d",p[x][y]);

那么我们现在就面临了一个一个问题——二维数组开多大?

1.p[10001][10001]
于是——运行错误
在这里插入图片描述
2.p[100001][100001]
于是——编译错误
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
哈哈哈哈,又被我耍了……

(如果你想知道这是为什么,文档后面E.3处有介绍)

C.改进算法

我们来看这一幅图:
在这里插入图片描述
从中我们想:如果我们预先设定好要查询的位置,再来查询,会不会快点呢?

看代码:

#include<bits/stdc++.h>
using namespace std;

int main(){
	int n,a[10000],b[10000],x[10000],y[10000],c,d;
	
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d%d%d%d",&a[i],&b[i],&x[i],&y[i]);//任它先输入 
	}
	scanf("%d%d",&c,&d);
	
	
	int m=-1;
	for(int i=n;i>=1;i--){//更省时哟 
		if(c>=a[i]&&c<=a[i]+x[i]&&d<=b[i]+y[i]&&d>=b[i]){//范围查找 
			m=i;
			printf("%d",m);
			return 0;
		}
	}
	printf("-1");
	return 0;
} 

这道题就完事了。

D.补充模块

1.喜闻见乐的NOIP介绍:

NOIP比赛

NOIP(National Olympiad in Informatics in Provinces,全国青少年信息学奥林匹克联赛)是一项面向全国青少年的信息学竞赛和普及活动。为NOI主管的一系列比赛之一,旨在向那些在中学阶段学习的青少年普及计算机科学知识,给学校的信息技术教育课程提供动力和新的思路;给那些有才华的学生提供相互交流和学习的机会。通过竞赛和相关的活动培养选拔优秀的计算机人才。初、高中或其他中等专业学校的学生可报名参加联赛。

竞赛形式:

竞赛赛制:

联赛分两个年龄组:初中组和高中组(普及组和提高组)。每组竞赛分两轮:初试和复试。各省市初试成绩在本赛区前百分之十五的学生进入复赛。
初试形式为笔试,侧重考察学生的计算机基础知识和编程的基本能力,并对知识面的广度进行测试。
复试形式为上机,侧重考察学生对问题的分析理解能力,数学抽象能力,驾驭编程语言的能力和编程技巧、想象力和创造性等。
初赛及复赛程序设计采用C、C++、Pascal语言,2022年后将不可使用Pascal、C语言,只能使用C++。

赛程赛事:

初赛:十月的第2个或第3个星期六下午14:30-16:30(普及,提高)
复赛:十一月的第2个星期六下午14:30-18:00(普及组)
十一月的第2个星期六上午8:30-12:00,星期日上午8:30-12:00(共2天,提高组)

自2017年来,由于参赛人数增多,NOIP复赛规模的规则进行了调整。包括:每个省赛区可以设立多于两个的复赛考点(但必须在同一个城市),初赛进入复赛的比例和规模由各省赛区自行决定,在条件许可的情况下,鼓励更多选手参赛。同时复赛获奖比例将基本保持不变,全国一等奖获奖比例约为复赛参赛选手的20%。

2.NOI网上报名系统

链接在此。
因为是中文界面,我就不演示了。

3.为什么会有这种效果

二维数组,假如是a[N][N],在128M空间的限制下,最多N不超过3000。因为9千万开根号是3000,而a[N][M],N*M不能大于9千万。

E.同主题文章链接

【信息学竞赛真题! ! !】「USACO2016」Subsequences Summing to Sevens题解(C++版)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值