C语言巧用数组之《校门外的树》+个人的一些见解
作为一个阅读能力比较差的同学,拿到一个问题描述非常长的题目是很苦恼的一件事。
在复习C语言时,看到acm上的一个题目,题目描述对我来说是比较长的了,但是题目却比较简单。
今天在这篇博客里,面对这么多大佬,卖弄一下,发表一些我的经验。
读者可以暂时跳过以下原题部分,直接看我的 个人体会。
【原题目】
某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米。我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置;数轴上的每个整数点,即0,1,2,……,L,都种有一棵树。
由于马路上有一些区域要用来建地铁。这些区域用它们在数轴上的起始点和终止点表示。已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。现在要把这些区域中的树(包括区域端点处的两棵树)移走。你的任务是计算将这些树都移走后,马路上还有多少棵树。
输入
数据有多组,对于每组输入:
输入的第一行有两个整数L和 M,L代表马路的长度,M代表区域的数目,L和M之间用一个空格隔开。接下来的M行每行包含两个不同的整数,用一个空格隔开,表示一个区域的起始点和终止点的坐标。
数据范围
1 <= L <= 10000, 1 <= M <= 100
输出
对于每组数据:
输出包括一行,这一行包含一个整数,表示马路上剩余的树的数目。
样例输入
500 3
150 300
100 200
470 471
样例输出
298
【个人体会】
拿到这个题目之后,我首先是比较烦恼的,看了三遍题目描述才明白是怎么回事,再看数据的时候发现这就是一个很简单的题目。
【简化描述】
先给定一条线上树的数量,每隔一米一棵树。有几段树要砍掉,在总树量的那一行给出段数。接下来每一行都将会给出起始位置,即第几米开始到第几米结束。
【解析】
第一眼看到题目,解题思路大致是要去做减法,把要砍掉的树减去即可。
但是实际操作,构建代码体系的时候会发现,这些要砍掉的树段中会出现重复的现象,做减法显然已经变得比较麻烦。
由此便可以想到题目中说到的坐标轴,不妨用数组构建一个坐标轴,即先使用相同的数据将坐标轴填充,再去用另一种数据代表砍掉的树。这样一来题目便简单多了。
【代码&注释】
#include<stdio.h>
int main()
{
int i,j,k,n,m,M,s=0;
//在定义变量的时候,个人是比较习惯盲目地去设一些变量
//比如本题中要使用数组,便直接将i,j等循环使用的变量先设出来
//这里可以不用先定义数组,因为不确定数组的长度(树总量),所以先扫描导入数组长度再行定义
scanf("%d %d",&M,&i);
int a[M];
//第一行的数据读取完了,可以定义数组和计算次数(要砍的树段数)了
for(k=0;k<=M;k++)
a[k]=1;
//这个循环是使用相同数据填充数组,即将树“种上”
for(j=0;j<i;j++){
scanf("%d %d",&m,&n);
for(k=m;k<=n;k++)
a[k]=0;
}
//用不同数据将要去掉的段改变,即“砍树”
for(k=0;k<=M;k++)
if(a[k]==1)
s++;
//计算剩余未改变数据数量,剩余的树量
printf("%d",s);
}
【代码】
#include<stdio.h>
int main()
{
int i,j,k,m,n,M,s=0;
scanf("%d %d",&M,&i);
int a[M];
for(k=0;k<=M;k++)
a[k]=1;
for(j=0;j<i;j++){
scanf("%d %d",&m,&n);
for(k=m;k<=n;k++)
a[k]=0;
}
for(k=0;k<=M;k++)
if(a[k]==1)
s++;
printf("%d",s);
}
【理解】
在我们使用C语言解决问题的时候,可以将要解决的问题理解成一个工程,指针、数组是我们要用的大材料。
在构建思路的时候,可以将一些问题抽象化,再简单化。比如本题中将数组中的数据抽象成一棵棵树;再用不同数据表示已经砍掉的树,这时便在这个抽象的过程中将问题简化。