个人主页:
专题分栏:洛谷刷题
一、题目
详细题目链接:
P1003 [NOIP2011 提高组] 铺地毯 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题目
为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。一共有 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)。
输出格式
输出共 11 行,一个整数,表示所求的地毯的编号;若此处没有被地毯覆盖则输出 -1
。
输入输出样例
输入: 输出: 3 3 1 0 2 3 0 2 3 3 2 1 3 3 2 2
-------------------------------------------------------
3 -1 1 0 2 3 0 2 3 3 2 1 3 3 4 5
数据范围
对于30%的数据,有 n≤2。
对于50%的数据,0≤≤a,b,g,k≤1000。
对于100%的数据,有 0≤n≤10000, 0≤a,b,g,k≤1000000。
=========================================================================
二、讲解
首先,要能耐下心去读题,题目不难,但是字多。
根据读题,要能发现几个点。第一个,把区域看作第一象限;第二个,编号从1开始;第三个,重合的区域是编号低的在下面;第四个,边界;第五个,数据范围。尤其是数据范围要特别注意。
在开始写代码的时候,我们还要去想想这个情景中的一些特殊的情况,就比如:所求的地面被覆盖的地毯编号是怎么算(这里的算不是要计算,所求的地面正好被多个地毯覆盖,输出哪个编号的地毯,是最上面的,最下面的还是按照某个规律进行输入)?
根据题目,我们知道输出的是最上面的地毯编号。
通过上面对问题的一系列的细节检索和自我提问,让我们对这个题目理解了一大部分。现在开始一步步的编写代码即可。
三、代码逐步编写
1、对一开始所需要的各种变量进行定义。根据输出的是最上面的地毯编号,一开始我是想一组一组的判断然后将最上边的编号记录下来,但是x,y是在a,b,g,k的下面输入的,所以这种的话,没有判断的条件,所以我决定用数组进行储存起来。
#include<stdio.h>
int arr[10000][4];//储存地毯的信息
int main()
{
int n;
int a, b, g, k;//地毯左下角的横坐标和纵坐标,地毯在横向上的长度和在纵向上的长度
scanf("%d", &n);
int flag = -1;//记录地毯的编号
int i = 0;//既是循环变量又相当于是地毯的数量
for (i = 0; i < n; i++)
{
scanf("%d%d%d%d", &a, &b, &g, &k);
arr[i][0] = a;
arr[i][1] = b;
arr[i][2] = g;
arr[i][3] = k;
}
int x, y;//所求地面
scanf("%d%d", &x, &y);
return 0;
}
2、开始进行条件的判断。
对下面注释进行解释
1)进行判断某个点是否在一个区域里,只需要看x,y是否在相对应的x和y的范围里面
这样画图看的话,是不是只要点的横坐标在2和2+3之间,纵坐标在3和3+3之间就相当于点在区域的里面。将这样的关系转化为代码即可。(注意的是边界值,如果点在地毯的边上,角上也算作覆盖,所以有等号哦)
#include<stdio.h>
int arr[10000][4];//储存地毯的信息
int main()
{
int n;
int a, b, g, k;//地毯左下角的横坐标和纵坐标,地毯在横向上的长度和在纵向上的长度
scanf("%d", &n);
int flag = -1;//记录地毯的编号
int i = 0;//既是循环变量又相当于是地毯的数量
for (i = 0; i < n; i++)
{
scanf("%d%d%d%d", &a, &b, &g, &k);
arr[i][0] = a;
arr[i][1] = b;
arr[i][2] = g;
arr[i][3] = k;
}
int x, y;//所求地面
scanf("%d%d", &x, &y);
i--;//找到储存最后一块地毯的数组下标
for (i; i >= 0; i--)
{
//进行判断某个点是否在一个区域里,只需要看x,y是否在相对应的x和y的范围里面
if (x >= arr[i][0] && x <= (arr[i][0] + arr[i][2]))
{
if (y >= arr[i][1] && y <= (arr[i][1] + arr[i][3]))
{
flag = i;
break;
}
}
}
if (flag == -1)
printf("-1");
else
printf("%d", flag + 1);//因为flag里面存的是数组下标,下标是从0开始的,而地毯编号是从1开始的,所以要+1
return 0;
}
给个三连吧!!!谢谢咯。