程序基本算法习题解析 数轴上有N条线段和M个点,已知每条线段的起点和终点,求每个点共在几条已知的线段上出现过,输出该点出现的次数。
题目:
在一个数轴上有N条线段,已知每条线段的起点和终点的值均在50000以内。有M个点,求每一个点共在几条已知的线段上出现过,并输出该点出现的次数。输入:第一行输入数字N,表示线段条数(N<=50000),接下来的N行,每行输入两个数,作为线段的起点和终点。第N+2行输入数字M,表示要求的点的个数。接下来的M行,每行输入一个整数,表示点的位置(M<=50000)。输出:对于每个输入的点,输出表示其出现次数的数值。
思路:
刚看到这个题目时,我觉得很简单,大致想了一下思路准备略过,后来扫了一眼书上答案,发现书上的思路和我很不一样,因此把此题分享出来,感觉多少能拓展一下解题思维。
我的思路:
将每条线段的起点和终点,每个点的位置,每个位置对应的出现次数分别用一个数组存放,然后遍历每个点(外层循环),遍历每条线段(内层循环),判断该点是否在某条线段上(点的位置大于线段的起点小于线段的终点),如果在某条线段上,则相应点位置上的出现次数加1。
书上思路:
设置一个数组记录每条线段的下标对应点的位置,若有一条线段经过某点,只需在读取这条线段时将该点对应下标的值加1即可,结束此操作后,数组中每个点对应的值即为该点对应的线段数,最后对每个输入的点直接输出该点所在的线段的个数。
代码如下:
(我的思路)
#include "stdafx.h"
#include<iostream>
using namespace std;
//个人思路
int main()
{
int N,M; //N:线段条数,M:点的个数
cout << "输入线段条数:";
cin >> N;
int *line_begin = new int[N]; //line_begin:线段的起点
int *line_end = new int[N]; //line_end:线段的终点
int i,j;
//输入线段的起点和终点
for(i=0;i<N;i++)
{
cout << "输入第" << i+1 << "条线段的起点和终点:";
cin >> line_begin[i] >> line_end[i];
}
cout << "输入点的个数:";
cin >> M;
int *point = new int[M]; //point:点的位置
int *point_num = new int[M]; //点的个数,对应于point
//初始化点的个数
for(i=0;i<M;i++)
{
point_num[i] = 0;
}
//输入点的位置
for(i=0;i<M;i++)
{
cout << "输入第" << i+1 << "个点的位置:";
cin >> point[i];
}
//遍历每个点
for(i=0;i<M;i++)
{
//遍历每条线段
for(j=0;j<N;j++)
{
//如果点在线段上(点的位置在线段的起点和终点之间)
if(point[i] >= line_begin[j] && point[i] <= line_end[j])
point_num[i]++;
}
}
for(i=0;i<M;i++)
{
cout << "点" << point[i] << "出现的次数为:" << point_num[i] << endl;
}
system("pause");
return 0;
}
(书上思路)
#include "stdafx.h"
#include<iostream>
using namespace std;
//书上思路
int s,e,p; //s:线段起点,e:线段终点,p:点的位置
int n,m; //n:线段条数,m:点的个数
int v[50010]; //每个单元位置上的点在所有线段中出现次数
int main()
{
cin >> n; //输入线段条数
for(int i=0;i<n;i++)
{
cin >> s >> e; //输入线段的起点和终点
for(int j=s;j<=e;j++)
{
v[j]++; //将该条线段覆盖到的点都加1
}
}
cin >> m; //输入点的个数
for(int k=0;k<m;k++)
{
cin >> p; //输入点的位置
cout << "点" << p << "出现的次数为:" << v[p] << endl; //将该位置的点出现次数输出
}
system("pause");
return 0;
}
运行结果如下:
(我的思路)
(书上思路)