电力输送网模拟

这么一个问题:

有一个学园,学园里有一位电工
电力输送网模拟
电工负责给学园里的各个部门送电,保证各部门的正常运行,同时不会因为负载过高造成事故。简单地说就是拉电闸的。
下面是整个学园的供电网络:
电力输送网模拟我们都要考虑什么??
1.为了保证电力充足供应,整个学园的电力由南北两条供电线路同时供应,假如发生事故导致某一条供电线路发生故障,可以通过调整电闸只用一条供电线路给整个学园供电
2.平时两条线路共用时要保证它们两部分是独立的,两条供电线路直接相连会造成短路事故。此外还要考虑一件事情,学园内部有一些 秘密设施 实验室 是及其耗电的,要给它们优先供电,所以电不能随便送,还是要考虑负载的,当然一个部分的负载有多大只能实时通过电表来测量。
3.除此之外呢,学院长还有个要求:我的电工不可以在前面的线路还没有送上电的情况下把后面闸合上。

那么作为一名维持整个学园正常运转的电工,应该怎么做呢?她找来了另一个时常接触电子设备的人,让她想办法写个程序来判断一个电闸拉下去之后会不会发送事故。
电力输送网模拟
那么我们作为一个程序员,该做什么呢?

解决思路

首先
把整个供电网络抽象成一个模型
电力输送网模拟

可以看到,图中各种蓝色的部分是输电线,它们都以w作为开头;红色的部分是电闸,以K开头的表示它是干线上的电闸,以L开头的表示它负责个某个具体部门供电,暂时可以不用关心那些标号后面的数字,后面才用得到。

一般思路

那么按照一般的思路,在拉下一个电闸之前判断一下它其他的电闸是否拉下
比如要给以 L1-1 为代表的学生宿舍1供电,有几种办法呢?
1:K1->K4->L1-1
2:K1->K3->K5->K8->K9->K7->L1-1
3:K1->K3->K5->K6->L1-1
4:K2->K3->K4->L1-1
5:K2->K5->K6->L1-1
6:K2->K5->K8->K9->K7->L1-1
还要保证
1:K1 K2 K3
2:K1 K2 K4 K5 K6
3:K1 K2 K4 K5 K7 K8 K9
这些开关不能同时闭合,会短路
此外还要在上面那几种情况中加一个顺序判断,也就是
K4 闭合时 K1 要先闭合,或者 K2 K3 先闭合,或者 K2 K5 K6 先闭合,或者 K2 K5 K8 K9 K7 先闭合。
这样给一号学生公寓的送电方案就完成了……
电力输送网模拟
一栋楼就搞这么麻烦,整个学园条件列完的不得肝爆啊!!!
除了麻烦外还有个更大的隐患,以后学园建个楼,或者再塌个楼,改个线路,所有的条件都要改,是个程序员就要吐血。

多年来的经验告诉我们,当一个办法行不通的时候,一般都是我们选错了办法,所以有没有别的办法呢?

引入图论的方法

重新回到上面的供电网络中来,再观察一下
电力输送网模拟这一个供电网络整体上是多对多的关系,各个单元,不论是电闸还是电线,它们都是一个连一个的,而且大部分都是一对多的关系,就像 W5 同时连接着7个电闸。然后输送电力的电流只是在电线和电闸之间流动,没有方向性,就像是电流可以从 W5 经 K4 流向 W3,它也可以从 W3 经 K4 流向 W5 。

觉不觉得这跟什么东西有点像?什么来着???

无向图
电力输送网模拟
是不是很像?
同样都是多节点之间的连接关系,图中没有方向性可言。
不过突然放出这么一个图来思路有点跳跃,我们来把输电网络中的一小部分切下来,用节点代表电线,用连线代表电闸,放到无向图中看看:

电力输送网模拟
这是一个给学生公寓1送电抽象出的无向图,节点 W1 W2 始终有电,其他的节点是否带电要看它能否通过电闸——连线与 W1 W2 连通。
思路是不是就很清晰了,只要某判断各节点与 W1 W2 的连通情况就能判断它是否有电了。这样就把原来的问题简化了,然后我们就可以动手编写程序了,是不是很激动。
电力输送网模拟

那么我们的程序应该怎么编呢????

编程思路

首先要在程序中创建这么一个图来,图中有两种单位,一个是电线(节点),另一个电闸是(连线)。

初始化图

我们可以用一个结构体或对象来对初始化一个图中的单位,结构体需要记录以下信息:
1.名称:人能看懂的名字
2.带电情况:ON/OFF
3.闭合情况(只在电闸中起作用):ON/OFF
4.种类:电线/电闸
5.连接项:与它相连的单位的代号

我在编程的时候初始化了一个一维结构体数组,表示图中的所有单位,这么做是因为我可以用数组中的编号来作为各单位的编号,也就是上面图中的那些数字的意义。
这样只要一个一个给这些单位都初始化了,配置好跟它相连的单位的标号,第一步就算完成。
这里给个建议:把所有的单位(W1 W2 除外)设置为不带电;把所有开关都断开;把所有单位的连接都设置为NULL,以后需要的时候再填写信息。因为这些步骤可以用循环搞定。给单位设置连接项很无聊,也有可能输错,但是必须亲力亲为,写好后多检查几遍。

设置操作方法

有了上面的图就可以进行各种操作了,其实也就只有一种操作——把电闸合上或断开,放到图里就是设置连线的通断。
写代码前再看看我们要考虑的条件

1.电闸闭合后可以输送电流
2.W1 W2 不能连通
3.电闸两端都不带电时,电闸不能闭合

所以当我们下达一个指令时,比如 K1 闭合,应该以这么一个顺序来执行:
1.K1 两端有带电的电线吗?有的话可以闭合,没有的话发出一次错误报告并不再向下执行
2.将 K1 设置为带电状态
3.遍历所有单位,使用深度优先遍历找到所有能通过带电单位连接到 W1 W2 的单位并将它们的状态设置为带电,如果不能连上 W1 W2 设置状态为不带电,假如是电闸,还要设置状态为断开。遍历过程中网络的每变化一次都要从头开始遍历,直到网络的状态不再发生变化。
4.监测 W1 W2 能否连通,如果可以就判断整个网络短路,报告错误。

建议:在遍历的时候有必要记录一下从哪一个单位遍历到当前单位的,不然程序会在某个环状结构中出不去,例如 W5->K6->W6->K8->W8->K9->W7->K7->W5

结束

经过上面的叙述,相信你已经大致了解到思路了,这是在图论中非常简单的知识,不过应用在电力输送中可能就不太常见了。这算是一种对多变量问题的解决方案,也可以把它用在各种能形成连接图的实际情景中,能做出什么来就看程序员的脑洞了,当然如果有其它更简单的办法欢迎留言。

整个模拟程序我写好了,逻辑上没有问题,说明这个思路是正确的。
不在这里放一行代码是因为编写用的是基础操作,自己编写也是一种乐趣,亲手把整个图给编出来也能带来更深入的了解,毕竟学习编程不亲自动手编就不能算学过。