数据结构期末复习·第五次作业·第四题·打印机网络选择&&最短路径

这个题貌似比第三题难,但是第三题属实折磨我更久

题面如下

【问题描述】

某单位信息网络结构呈树型结构,网络中节点可为交换机、计算机和打印机三种设备,计算机和打印机只能位于树的叶节点上。如要从一台计算机上打印文档,请为它选择最近(即经过交换机最少)的打印机。

在该网络结构中,根交换机编号为0,其它设备编号可为任意有效正整数,每个交换机有8个端口(编号0-7)。当存在多个满足条件的打印机时,选择按树前序遍历序排在前面的打印机。

image.png

【输入形式】

首先从标准输入中输入两个整数,第一个整数表示当前网络中设备数目,第二个整数表示需要打印文档的计算机编号。两整数间以一个空格分隔。假设设备总数目不会超过300。

然后从当前目录下的in.txt读入相应设备配置表,该表每一行构成一个设备的属性,格式如下:

<设备ID> <类型> <设备父节点ID> <端口号>

<设备ID>为一个非负整数,表示设备编号;<类型>分为:0表示交换机、1表示计算机、2表示打印机;<设备父结点ID>为相应结点父结点编号,为一个有效非负整数;<端口号>为相应设备在父结点交换机中所处的端口编号,分别为0-7。由于设备配置表是按设备加入网络时的次序编排的,因此,表中第一行一定为根交换机(其属性为0 0 -1 -1);其它每个设备结点一定在其父设备结点之后输入。每行中设备属性间由一个空格分隔,最后一个属性后有换行符。

【输出形式】

向控制台输出所选择的打印机编号,及所经过的交换机的编号,顺序是从需要打印文档的计算机开始,编号间以一个空格分隔。

【样例输入】

37 19

in.txt中的信息如下:

0 0 -1 -1

1 0 0 0

2 0 1 2

3 1 1 5

4 0 0 1

5 1 4 0

6 2 2 2

7 0 4 2

8 0 0 4

9 0 2 0

10 0 9 0

11 2 10 3

12 0 9 2

13 0 7 0

14 0 13 0

15 2 7 3

16 0 8 1

17 0 16 0

18 1 17 5

19 1 9 5

20 0 12 1

21 1 14 1

22 1 14 2

23 1 13 2

24 1 12 5

25 0 20 1

26 1 20 2

27 0 14 7

28 0 16 1

29 1 4 3

30 0 16 7

31 0 28 0

32 2 31 0

33 1 30 2

34 1 31 2

35 0 31 5

36 1 35 3

【样例输出】

11 9 10

【样例说明】

样例输入中37表示当前网络共有37台设备,19表示编号为19的计算机要打印文档。in.txt设备表中第一行0 0 -1 -1表示根节点交换机设备,其设备编号为0 、设备类型为0(交换机)、父结点设备编号-1表示无父设备、端口-1表示无接入端口;设备表第二行1 0 0 0表示设备编号为1 、设备类型为0(交换机)、父结点设备编号0(根交换机)、端口0表示接入父结点端口0;设备表中行5 1 4 0表示设备编号为5 、设备类型为1(计算机)、父结点设备编号4、端口0表示接入4号交换机端口0;设备表中行6 2 2 2表示设备编号为6 、设备类型为2(打印机)、父结点设备编号2、端口2表示接入2号交换机端口2。

样例输出11 9 10表示选择设备编号为11的打印机打印文档,打印需要经过9号和10号交换机(尽管6号和11号打印机离19号计算机距离相同,但11号打印机按树前序遍历时排在6号之前)。

【评分标准】

按题目要求实现相关功能,提交程序文件名为print.c。

采用的解法很暴力:

先dfs出所有的打印机节点,存储到一个数组里面;

然后遍历这个数组,分别求出最短路径,取最短的那条输入;

而对于计算最短路径的方法:

若要求节点p,q之间的最短路径,首先需要寻找他们的最深层公共祖先(要让pq联通,路径肯定是要过其公共祖先的,而求出最小的(最深层)的祖先,肯定是最短的)

而要求公共祖先,就抽象成了两个有序集合求交集的问题。最暴力的方法就是遍历一个集合,然后判断遍历到的元素是不是在另一个集合内,所以:从p开始,一层一层往上找其parent节点,若这个parent节点是q的祖先,则就找到了。

这时候我们已经走完了p到公共祖先的路程,接下来用ride2函数,从公共祖先走到q,只需要一个简单的dfs即可。注意路径长度使用递归返回值比用回溯来得方便。

最后按照和上面同样的方法,打印这条路径就好了。

代码如下(蹩脚英语注释又来辣)

#include <stdio.h>
#include <stdlib.h>

typedef struct node_type
{
	int number;
	int type;
	int parent; //the number of it's parent
	struct node_type *child[10];
} node; //node of tree

node *root;

node *search(node *p, int key)
{
	if (p->number == key)
		return p;
	if (p->child[0] == NULL && p->child[1] == NULL && p->child[2] == NULL && p->child[3] == NULL && p->child[4] == NULL && p->child[5] == NULL && p->child[6] == NULL && p->child[7] == NULL)
		return NULL;
	for (int i = 0; i < 10; i++)
	{
		if (p->child[i] != NULL && search(p->child[i], key) != NULL)
			return search(p->child[i], key);
	}
	return NULL;
} //search the node whose number is a given key, then return the address of this node

void pre_order(node *p)
{
	printf("%d %d\n", p->number, p->type);
	for (int i = 0; i < 10; i++)
	{
		if (p->child[i] != NULL)
			pre_order(p->child[i]);
	}
}

node *printer[1024];
int printer_num = 0;
void get_printer(node *p)
{
	if (p->type == 2)
		printer[printer_num++] = p;
	for (int i = 0; i < 10; i++)
	{
		if (p->child[i] != NULL)
			get_printer(p->child[i]);
	}
} //to find all the printers, and record them in the array printer;

int is_ances(node *anc, node *p)
{
	for (int i = 0; i < 10; i++)
	{
		if (anc->child[i] == p)
			return 1;
		if (anc->child[i] != NULL && is_ances(anc->child[i], p))
			return 1;
	}
	return 0;
} //judge if anc is the ancestor of p

int ride2(node *t, node *q)
{
	int len = 1;
	for (int i = 0; i < 10; i++)
	{ //search q:dfs
		if (t->child[i] == q)
			return len;
		if (t->child[i] != NULL && is_ances(t->child[i], q))
			return len + ride2(t->child[i], q);
	}
	return len;
} //in this function t is the ancestor of p,q u find in ride function

int ride(node *p, node *q)
{
	node *t = search(root, p->parent);
	int len = 1;
	while (is_ances(t, q) == 0)
	{ //to find the deepest shared ancestor of q and p,which names t
		t = search(root, t->parent);
		len++;
	}

	len += ride2(t, q); //the you need to find the way between t and q by function ride2

	return len;
} //find the shortest ride between 1 p, q

/*these two functions are same as before,just need to print the number while you go along the ride*/
void show_ride2(node *t, node *q)
{
	for (int i = 0; i < 10; i++)
	{
		if (t->child[i] == q)
		{
			printf("%d ", t->number);
			return;
		}
		if (t->child[i] != NULL && is_ances(t->child[i], q))
		{
			printf("%d ", t->number);
			show_ride2(t->child[i], q);
			return;
		}
	}
}

void show_ride(node *p, node *q)
{
	node *t = search(root, p->parent);
	while (is_ances(t, q) == 0)
	{
		printf("%d ", t->number);
		t = search(root, t->parent);
	}

	show_ride2(t, q);
}

int main()
{
	root = (node *)malloc(sizeof(node));
	int n;
	scanf("%d", &n);
	for (int i = 0; i < 10; i++)
		root->child[i] = NULL;

	FILE *in;
	in = fopen("in.txt", "r");
	while (n--)
	{
		int num;
		int ty;
		int par;
		int k;
		fscanf(in, "%d%d%d%d", &num, &ty, &par, &k);
		if (par == -1)
		{ //if it is root
			root->number = num;
			root->type = ty;
			root->parent = 0;
		}
		else
		{								 //if is not root
			node *t = search(root, par); //find it's parent and insert them
			node *p = (node *)malloc(sizeof(node));
			p->number = num;
			p->type = ty;
			p->parent = par;
			for (int i = 0; i < 10; i++)
				p->child[i] = NULL;
			t->child[k] = p;
		}
	}
	//pre_order(root);

	int s;
	scanf("%d", &s);
	node *src = search(root, s);

	get_printer(root); //get all the printers by pre order traverse
	//for(int i=0;i<printer_num;i++) printf("%d ",printer[i]->number);

	node *min_p = printer[0];
	int min_way = ride(src, printer[0]);
	for (int i = 0; i < printer_num; i++)
	{
		if (ride(src, printer[i]) < min_way)
		{
			min_way = ride(src, printer[i]);
			min_p = printer[i];
		}
	} //find the shortest way
	printf("%d ", min_p->number);
	show_ride(src, min_p);

	fclose(in);
}

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值