看前须知
考试回顾
网络打印机选择(北京学院数据结构18级期末压轴题)——伪树状数组(这题杀我)(ಥ_ಥ).
图的直径(士谔书院15级期末)——求有向图的最大路径:Floyd的妙用.
快逃离卷怪统治的BUAA——求树中的最短路径+中序和后序恢复二叉树.
网络打印机延迟率计算(士谔18级期末改编)——伪树状数组+树的直径.
题目内容
问题描述
一个内存空间块可用一对起始地址和结束地址表示,如[0,100]。对于两个内存空间块:[0,100]和[101,200],这两个空间是相邻的,所以可以合并成一个空间块:[0,200]。编写程序,输入一组空闲内存空间,对相邻空间进行合并,然后按照空间块的起始地址由小到大输出。注意:内存空间块不会存在重叠的情况。
算法之一提示:可先将输入的空间块按起始地址排序,然后进行合并。
输入形式
从控制台输入内存空间块的个数(大于等于1,小于等于100),然后分行输入每个内存空间块的起始地址和结束地址(地址用大于等于0,并且小于等于100000的整数表示),两地址间以一个空格分隔。
输出形式
将合并后的内存空间块按照空间块的起始地址由小到大输出**,每个空间块独占一行**,先输出起始地址,再输出结束地址,两地址间以一个空格分隔。
样例
样例输入:
10
48 99
0 39
1024 2047
100 479
4000 5999
600 799
40 47
2048 3047
840 859
8000 8999
样例输出:
0 479
600 799
840 859
1024 3047
4000 5999
8000 8999
样例说明
输入了10个内存空间块,其中:[0,39]、[40,47]、[48,99]和[100,479]相邻,可以合并成一个空间块:[0,479];[1024,2047]和[2048,3047]相邻,可以合并成[1024,3047]。合并后还有6个内存空间块,按照空间块的起始地址由小到大输出。
题解
思考和详解
和连续线段那道题一模一样,只要会结构体二级排序,这道题真的有手就行。对于已经合并的区块,我们可以把起点设置为-1(题目要求起点一定大于等于0),输出的时候就可以巧妙的避免输出它们了。
参考代码
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<ctype.h>
#include<stdbool.h>
int i,j;
struct node{
int a; //起点
int b; //终点
}s[20000];
int compare(const void*p1,const void*p2)
{
struct node *x=(struct node*)p1;
struct node *y=(struct node*)p2;
if(x->a!=y->b)return x->a-y->a; //先排起点
else return x->b-y->b; //再排终点
}
int main()
{
int n;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d %d",&s[i].a,&s[i].b); //输入
}
qsort(s,n,sizeof(struct node),compare); //排序
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(s[i].b+1==s[j].a) //满足合并条件
{
s[i].b=s[j].b;
s[j].a=-1; //巧妙设为-1(题目说起点一定大于等于0)
}
}
}
qsort(s,n,sizeof(struct node),compare); //再排
for(i=0;i<n;i++)
if(s[i].a!=-1) //如果不是已经合并的
printf("%d %d\n",s[i].a,s[i].b); //输出
return 0;
}