【清华集训】2017 无限之环

无限之环


题目

链接

洛谷

描述

曾经有一款流行的游戏,叫做 Infinity Loop,先来简单的介绍一下这个游戏:

游戏在一个 n ∗ m 的网格状棋盘上进行,其中有些小方格中会有水管,水管可能在

格某些方向的边界的中点有接口,所有水管的粗细都相同,所以如果两个相邻方格的

共边界的中点都有接头,那么可以看作这两个接头互相连接。水管有以下 15 种形状:

游戏开始时,棋盘中水管可能存在漏水的地方。

形式化地:如果存在某个接头,没有和其它接头相连接,那么它就是一个漏水的

地方。

玩家可以进行一种操作:选定一个含有非直线型水管的方格,将其中的水管绕方格

中心顺时针或逆时针旋转 90 度。

直线型水管是指左图里中间一行的两种水管。

现给出一个初始局面,请问最少进行多少次操作可以使棋盘上不存在漏水的地方。

输入格式

从文件 infinityloop.in 中读入数据。

第一行两个正整数 n, m,代表网格的大小。

接下来 n 行每行 m 个数,每个数是 [0,15] 中的一个,你可以将其看作一个 4 位的

二进制数,从低到高每一位分别代表初始局面中这个格子上、右、下、左方向上是否有

水管接头。

特别地,如果这个数是 0 ,则意味着这个位置没有水管。

比如 3(0011(2)) 代表上和右有接头,也就是一个 L 型,而 12(1100(2)) 代表下和左

有接头,也就是将 L 型旋转 180 度。

输出格式

输出到文件 infinityloop.out 中。

输出共一行,表示最少操作次数。如果无法达成目标,输出-1.

子任务

解题法

评价:神奇的网络流神题

出这种题的dalao,%%%

Round 1:黑白染色

对于一个方格,黑白染色后,就分成了两个部分,并且保证同色之间不连边。对于一个格子,需要连接的就是上下左右,全部与原方格异色。

Round 2:方格->网络流的边

拆点,建图。
这道题的精髓就体现在建图。
(未经说明的边均与S或T相连)

单头型

这里写图片描述

四条边分别是:
- 向上,容量1,费用0。
- 向左右,容量1,费用1。
- 向下,容量1,费用2。

直线型(不能动)

以上下(编号5)为例,建的边有:

  • 向上下,容量1,费用0。
弯弯1

要命的就是转来转去怎么办?

顺时针转90°其实相当于把上面那根管子搞到下面来,费用为1。
转180°同理,两根一起调头,费用为2。
于是我们就解决了这么一个问题。

建的边有:
- 向上,容量1,费用0。
- 向右,容量1,费用0。
- 向下与向上相连,容量1,费用1。
- 向左与向右相连,容量1,费用1。

应为容量只有1,所以想要跑出转180°的那种情况费用必须为2.。
(完美!)

弯弯2

以我们的经验,可以秒掉其中三条边:
- 向左右上,容量1,费用0。
仔细一想,发现空的那个地方其实可以由三条边转移而来,
再结合弯弯2型的另外三个图,其实很容易发现剩余边的建法:
- 向左与向下相连,容量1,费用1。
- 向右与向下相连,容量1,费用1。
- 向上与向下相连,容量1,费用2。

十字型

最无脑的。
- 向上下左右,容量1,费用0.。

结束!

至此,我们就完成了建边过程。

至于细枝末节的问题,不再讨论(这不本质)

Round 3:网络流乱跑!

费用流即可。

代码:

#include<bits/stdc++.h>

#define FN "infinityloop"

const int MN=2000+5;
const int N=8000+5;
const int INF=1e9+7;

namespace LoLiK {

    struct Edge {
        int v,nxt,cot,fow;
    }e[20*N];

    int S,T,n,m,id[MN][MN][4];
    int h[N],tot=1,cnt=0;
    int dx[4]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值