数据结构_课程设计——最小生成树:室内布线

***************************************转载请注明出处:http://blog.csdn.net/lttree********************************************

这道课程设计,费不少时间,太麻烦了= =。(明明是能力不够

~~~~最小生成树:室内布线~~~~

题目要求:

装修新房子是一项颇为复杂的工程,现在需要写个程序帮助房主设计室内电线的布局。

首先,墙壁上插座的位置是固定的。插座间需要有电线相连,而且要布置的整齐美观,即要求每条线都与至少一条墙边平行,且嵌入四壁或者地板(不能走屋顶)。

房主要求知道,要将所有插座连通,自己需要买的电线的最短长度。

另外,别忘了每个房间都有门,电线不可以穿门而过。上图给出了一个有4插座的房间的电线布局。

输入要求:

输入由若干组测试数据组成。

每组数据的第1行包含房间的长、宽、高和插座的个数N(N为一个不超过20的正整数)。

接下去的N行中,第i行给出第i个插座的位置坐标(xi,yi,zi);最后一行包含4个3元组(x1,y1,z1)…(x4,y4,z4),分别是长方形门框的4个角三维坐标。4个数字全部为0表示全部测试结束,不要对该数据任何处理。

注意:这里假设长方体形状的房间完全位于三维直角坐标系的第一象限内,并且有一个角落在原点上。地板位于x-y平面。题目数据保证,每个插座仅属于四面墙中的一面,门上没有插座。要求每段电线的两端必须仅与插座连接,电线之间不能互相交叉焊接。

输出要求:

对每一组测试,在一行里输出要将所有插座连通需要买的电线的最短整数长度。

输入例子:

10 10 10 4

0 1 3.3

2.5 0 2

5 0 0.8

5 10 1

0 0 0 0 0 3 1.5 0 0 1.5 0 3

0 0 0 0

输出例子:

21

这道题,注意以下几点:

① 布线要与墙平行

② 两插座位置关系

③ 线可以走地面,不可以走屋顶和门

④ 最后数据,向上取整

然后,题目考查的是最小生成树,但我花了很多时间求两插座之间的距离= =。。

我代码注释中出现的 1,2,3,4  4个面为:正对着我们的为 1号面,我们正对着1号面,它的左面为2号面,1号面右面为3号面,1号面相对着4号面。

然后,程序是:

/*******************************************
********************************************
*           Author:Tree                    *
*    From :  blog.csdn.net/lttree          *
*      Title : 最小生成树:室内布线        *
*    Source: 数据结构_课程设计             *
*      Hint :  最小生成树                  *
********************************************
*******************************************/   

#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std;

/******  一些相关变量的定义 ******/

// 插座个数,最多为20个,所以,边最多只有400个
#define MAX 401
// 点的结构体
struct Node
{
	double x,y,z;
}nd[21],door[4];
// 含权值的边的结构体
struct Edge
{
	int u;
	int v;
	double quan;
}eg[MAX];
// N - 插座个数,len,wid,hei - 房间的长、宽、高,pos_door门所在位置
int N,len,wid,hei,pos_door;
int father[21];

/******  判断两插座位置关系  ******/

// 是否在同一墙面
bool isTogether( Node a , Node b )
{
	if( (a.x==b.x && (a.x==0||a.x==len) ) || (a.y==b.y && (a.y==0||a.y==wid) ) )	return true;
	return false;
}
// 判断是否在相邻墙面
bool isBeside( Node a , Node b )
{
	if( a.x==0 || a.x==len )
	{
		if( b.y==0 || b.y==wid )
			return true;
		else
			return false;
	}
	else if( a.y==0 || a.y==wid )
	{
		if( b.x==0 || b.x==len )
			return true;
		else
			return false;
	}
}
// 是否在相对墙面
bool isAcross( Node a , Node b )
{
	if( (a.x==0 && b.x==len) || (a.y==0 && b.y==wid) || (a.x==len && b.x==0) || (a.y==wid && b.y==0) )
		return true;
	else
		return false;
}

/******  一系列判断  ******/

// 求最小值
double Min( double a,double b)
{
	return a<b?a:b;
}
// 判断门在哪个墙面
int judge_d( Node d[] )
{
	if( d[0].y==0 && d[3].y==0 )	return 1;
	else if( d[0].x==0 && d[3].x==0 )	return 2;
	else if( d[0].x==len && d[3].x==len )	return 3;
	else if( d[0].y==wid && d[3].y==wid )	return 4;
}
// 判断两个同墙插座间连线是否穿门
bool judge_crossdoor( Node n1, Node n2 )
{
	// 如果插座在最下面,或者插座位置高于门的位置,则不穿过门(无论墙和插座位置关系如何)
	if( n1.z==0 || n2.z==0 || n1.z>=door[3].z || n2.z>=door[3].z )	return false;
	if( pos_door==1 )
	{
		if( n1.y!=0 && n2.y!=0 )	return false;
		if( (n1.x>=door[3].x && n2.x>=door[3].x) || (n1.x<=door[0].x && n2.x<=door[0].x) )	return false;
		return true;
	}
	else if( pos_door==2 )
	{
		if( n1.x!=0 && n2.x!=0 )	return false;
		if( (n1.y<=door[0].y && n2.y<=door[0].y) || (n1.y>=door[3].y && n2.y>=door[3].y) )	return false;
		return true;
	}
	else if( pos_door==3 )
	{
		if( n1.x!=len && n2.y!=len )	return false;
		if( (n1.y<=door[0].y && n2.y<=door[0].y) || (n1.y>=door[3].y && n2.y>=door[3].y) )	return false;
		return true;
	}
	else
	{
		if( n1.y!=wid && n2.y!=wid )	return false;
		if( (n1.x>=door[3].x && n2.x>=door[3].x) || (n1.x<=door[0].x && n2.x<=door[0].x) )	return false;
		return true;
	}
}

/******  求布线长度  ******/

// 求同墙两插座最短布线
double find_togcost( Node a,Node b )
{

	// 两插座同墙且不穿门
	if( !judge_crossdoor( a , b ) )
		return (fabs(a.x-b.x)+fabs(a.y-b.y)+fabs(a.z-b.z));
	else
	{
		// 两插座布线会穿过门,门的位置不同
		if( pos_door==1 || pos_door==4 )	return Min( (fabs(a.x-b.x)+fabs(door[3].z-a.z)+fabs(door[3].z-b.z) ),(fabs(a.x-b.x)+a.z+b.z) );
		else	return	Min( (fabs(a.y-b.y)+fabs(door[3].z-a.z)+fabs(door[3].z-b.z)),(fabs(a.y-b.y)+a.z+b.z) );
	}
}
// 求相对墙两插座最短布线
double find_acrcost( Node a,Node b )
{
	double cost1,cost2;
	Node temp1,temp2;
	// 插座在1,4面
	if( (a.y==0 && b.y==wid) || (b.y==0 && a.y==wid) )
	{
		// 根据门的位置,求权值
		if( pos_door==1 )	return	Min( Min( (a.y+fabs(door[3].z-a.z)+len+b.y),(a.y+a.z+len+b.y) ),Min( (wid-a.y+len+wid-b.y),(a.z+len+b.z) ) );
		else if( pos_door==2 )
		{
			temp1=temp2=a;
			temp1.y=0,temp2.y=wid;
			cost1=find_togcost(a,temp1);
			cost2=find_togcost(a,temp2);
			return	Min( (cost1+len+b.y),(cost2+len+wid-b.y) );
		}
		else if( pos_door==3 )
		{
			temp1=temp2=b;
			temp1.y=0,temp2.y=wid;
			cost1=find_togcost(b,temp1);
			cost2=find_togcost(b,temp2);
			return	Min( (cost1+len+a.y),(cost2+len+wid-a.y) );
		}
		else	return	Min( Min( (a.y+len+b.y),(wid-a.y+wid-b.y+fabs(door[3].z-a.z)+len) ), Min( (wid-a.y+wid-b.y+a.z+len),(a.z+b.z+len) ) );

	}
	else
	{
		if( pos_door==1 )
		{
			temp1=temp2=a;
			temp1.x=0,temp2.x=len;
			cost1=find_togcost(a,temp1);
			cost2=find_togcost(a,temp2);
			return	Min( (cost1+wid+b.x),(cost2+wid+len-b.x) );
		}
		else if( pos_door==2 )	return Min( Min( (a.x+b.x+wid+fabs(door[3].z-a.z)),(a.x+b.x+wid+a.z) ),Min( (len-a.x+len-b.x+wid),(a.z+b.z+wid) ) );
		else if( pos_door==4 )
		{
			temp1=temp2=b;
			temp1.x=0,temp2.x=len;
			cost1=find_togcost(b,temp1);
			cost2=find_togcost(b,temp2);
			return Min( (cost1+wid+a.x),(cost2+wid+len-a.x) );
		}
		else return Min( Min( (a.x+b.x+wid),(a.z+b.z+wid) ),Min( (len-a.x+len-b.x+fabs(door[3].z-a.z)+wid),(len-a.x+len-b.x+a.z+wid) ) );
	}
}
// 求相邻墙两插座最短布线
double find_bescost( Node a , Node b )
{
	Node temp=a;
	// 在两平面连接处找一个点(让其中一点x,y为0即可),转化为两个 同墙插座 问题
	if( (a.x==0 && b.y==0) || (b.x==0 && a.y==0) )
	{
		temp.x=temp.y=0;
		return ( find_togcost(a,temp)+find_togcost(b,temp) );
	}
	else if( (a.x==len && b.y==0) || (a.y==0 && b.x==len) )
	{
		temp.x=len,temp.y=0;
		return ( find_togcost(a,temp)+find_togcost(b,temp) );
	}
	else if( (a.x==0 && b.y==wid) || (b.x==0 && a.y==wid) )
	{
		temp.x=0,temp.y=wid;
		return ( find_togcost(a,temp)+find_togcost(b,temp) );
	}
	else
	{
		temp.x=len,temp.y=wid;
		return ( find_togcost(a,temp)+find_togcost(b,temp) );
	}
}

/******  求最小生成树(Kruscal)  ******/

// 比较函数
bool cmp(Edge e1,Edge e2)
{
    return e1.quan<e2.quan;
}
// 并查集 初始化函数
void Init( int m )
{
    int i;
    for(i=1;i<=m;i++)
        father[i]=i;
}
// 并查集 查找函数
int Find(int x)
{
    while(father[x]!=x)
        x=father[x];
    return x;
}
// 并查集 合并函数
void Combine(int a,int b)
{
    int temp_a,temp_b;
    temp_a=Find(a);
    temp_b=Find(b);  

    if(temp_a!=temp_b)
        father[temp_a]=temp_b;
}
// 最小生成树 Kruskal 算法
double Kruskal( int n )
{
    Edge e;
    int i;
	double res;
    sort(eg,eg+n,cmp);
    // 并查集 初始化
    Init(N);  

    // 构建最小生成树
    res=0;
    for( i=0;i<n;++i )
    {
        e=eg[i];
        if( Find(e.u)!=Find(e.v) )
        {
            Combine(e.u,e.v);
            res+=e.quan;
        }
    }
    return res;
}  

/****** 主函数 ******/

void main()
{
	// i,j 为中间变量,k为边的个数
	int i,j,k;
	while( cin>>len>>wid>>hei>>N )
	{
		// 输入数据为4个0,则退出程序
		if( !len && !wid && !hei && !N )	break;

		// 获取数据(插座与门的位置)
		for( i=0 ; i<N ; ++i )
			cin>>nd[i].x>>nd[i].y>>nd[i].z;
		for( i=0 ; i<4 ; ++i )
			cin>>door[i].x>>door[i].y>>door[i].z;
		pos_door=judge_d( door );

		/* 求两点间距离(注意,布线要与墙平行) */
		k=0;
		for( i=0 ; i<N ; ++i )
		{
			for( j=i+1; j<N ; ++j )
			{
				eg[k].u=i;
				eg[k].v=j;
				// 判断两点关系,同墙or相邻墙or相对墙

				// 同墙
				if( isTogether( nd[i] , nd[j] ) )	eg[k].quan=find_togcost(nd[i],nd[j]);
				// 相对墙
				else if( isAcross( nd[i] , nd[j] ) )	eg[k].quan=find_acrcost(nd[i],nd[j]);
				// 相邻墙
				else	eg[k].quan=find_bescost(nd[i],nd[j]);
				++k;
			}
		}

		/* 用Kruscal算法求最小生成树 */
		// 注意最后,无论长度如何,都要向上取整
		double cost;
		cost=Kruskal(k);
		if( cost-int(cost)==0 )	cout<<cost<<endl;
		else	cout<<int(cost+1)<<endl;
	}
}

***************************************转载请注明出处:http://blog.csdn.net/lttree********************************************

时间: 2024-10-12 14:47:15

数据结构_课程设计——最小生成树:室内布线的相关文章

数据结构_课程设计——并查集:检查网络

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 这两天做数据结构课程设计,因为以前做过ACM题,感觉还可以,不是很难呀 ~~~~并查集:检查网络~~~~ 题目要求: 给定一个计算机网络以及机器间的双向连线列表,每一条连线允许两端的计算机进行直接的文件传输,其他计算机间若存在一条连通路径,也可以进行间接的文件传

在线抢购平台_课程设计报告

第1章 概述 1.1 课程设计的核心任务 需求分析.可行性分析.E-R图.关系图.系统架构图等的编写 总体设计.详细设计.代码实现 项目测试 本系统: 后端采用SSM(Spring+SpringMVC+MyBatis)的架构,实现RESTful API 接口,前端采用react进行前后端分离设计,完成商品在线系统. 1.2 课程设计工作进程 已经完成,用户登录注册,商品的添加,活动促销的添加,商品的查看与秒杀. 后续继续完成,订单页面的优化与完成,针对高并发下单任务的处理,针对用户重复秒杀商品的

课程设计 --- 黑白棋中的 AI

原文链接:https://www.dreamwings.cn/reversi/3013.html 到了考试周了佯,可是偏偏这个时候迎来了很多很多的课程设计,幸好教授把C语言的课程设计提前发出了,不然都在最后几周,加上数据结构的课程设计就没有时间做这个啦~ 刚开始打算做成UWP应用的,可是网上的教程都是C#,并且用C++做的话某些功能和C#不一样,所以就这样拖了好多周,省赛前一点儿也没有开始做,等到省赛结束之后,别人都差不多完成啦!而我才开始准备查找资料-- 然而一周过去了,进度还是0%.噫,1%

数据结构课程设计题目四_二叉树

本文出自:http://blog.csdn.net/svitter 题目4:二叉树 给出一颗无线的二叉树.树的每一个结点用一整数对标识.二叉树构造如下 树根被标识为(1, 1): 如果一个结点被标识为(a, b), 则其左孩子被标识为(a+b,b),右孩子被标识为(a, a+b).现在给出某一结点(a, b),求树根到该结点的最短路径,并且同时求出从树根出发向左走和向右走的次数.建议完成人数1人. 注:此处使用了STL_stack库函数,是不允许的,我图方便. //===============

数据结构课程设计题目十二_计算机学院学生会的打印机(优先队列)

本文出自:http://blog.csdn.net/svitter 题目12:计算机学院学生会的打印机(优先队列) 小明抱怨学生会的打印机不符合FIFO的原则,看到很多在他后面来打印的同学比他先打印出来.五分钟前,小明的文件就是下一个候选的,如今小明的文件又排到了后面.学生会的同学给小明解释说,学生会的打印机不是採用传统的队列方式,而是採用一种自定义的优先队列方式:每一个要打印的文件被赋予了一个从1到9的优先级(9最高,1最低).打印规定例如以下: 将队列中要打印的文件f从队列中拿出来: 假设在

数据结构——课程设计

  <数据结构课程设计>   课程题目 模拟电话客服管理系统 课程编号 j1620102 学生姓名 吴佳煜 所在专业 信息管理与信息系统 所在班级 信管1133 任课老师 易学明 实习时间 二〇一四年十二月二十五日 设计成绩 老师评语 一.课程设计题目 赵斌是一个信管专业的学生,大学四年顺利毕业了.在毕业季,他也像其他学子一样,投身于求职大军,投出一份又一份求职简历,在苦苦地等待之后,他接到了中国移动通信公司广东分司的面试通知书,通知他于本月1号10点到公司面试.当天,晴空万里,艳阳高照,他身

数据结构课程设计《稀疏矩阵运算器》

最近正在弄数据结构课程设计内容,说实话,感觉自己数据结构学的就是渣,好多东西都不会.还是要多学点东西啊.现在暂且贴点之前写完的东西吧,到时候也好有个总结. 1 诸论 1.1 问题描述 稀疏矩阵是指那些多数元素为零的矩阵.利用"稀疏"特点进行存储和计算可以大大节省存储空间,提高计算准备效率.实现一个能进行稀疏矩阵基本运算的运算器. 1.2 基本要求 以"带行逻辑链接信息"的三元组顺序表示稀疏矩阵,实现两个稀疏矩阵相加.相减.相乘和求逆的运算.稀疏矩阵的输入形式采用三元

数据结构课程设计

20. 公交线路上优化路径的查询  问题描述 最短路径问题是图论中的一个经典问题,其中的Dijkstra算法一直被认为是图论中的好算法,但有的时候需要适当的调整Dijkstra算法才能完成多种不同的优化路径的查询. 对于某城市的公交线路,乘坐公交的顾客希望在这样的线路上实现各种优化路径的查询.设该城市的公交线路的输入格式为: 线路编号:起始站名(该站坐标):经过的站点1名(该站坐标):经过的站点2名(该站坐标):--:经过的站点n名(该站坐标):终点站名(该站坐标).该线路的乘坐价钱.该线路平均

数据结构课程设计之一元多项式的计算

数据结构不是听会的,也不是看会的,是练会的,对于写这么长的代码还是心有余也力不足啊,对于指针的一些操作,也还是不熟练,总出现一些异常错误,对于数据结构掌握还是不够啊,还是要多练,这个课程设计做的还是有点粗糙,还有待改进啊!! 对代码有进行了一下改进,增加了排序的模块:可能还存在着一下小bug,发现了再更新:减法还可以写的更简便一点. <pre name="code" class="cpp">#include <stdio.h> #includ