Loj #2321. 「清华集训 2017」无限之环
Loj #2321. 「清华集训 2017」无限之环
曾经有一款流行的游戏,叫做 *Infinity Loop***,先来简单的介绍一下这个游戏:
游戏在一个 \(n \times m\) 的网格状棋盘上进行,其中有些小方格中会有水管,水管可能在方格某些方向的边界的中点有接口,所有水管的粗细都相同,所以如果两个相邻方格的公共边界的中点都有接头,那么可以看作这两个接头互相连接。水管有以下 \(15\) 种形状:


游戏开始时,棋盘中水管可能存在漏水的地方。
形式化地:如果存在某个接头,没有和其它接头相连接,那么它就是一个漏水的地方。
玩家可以进行一种操作:选定一个含有*非直线型*水管的方格,将其中的水管绕方格中心顺时针或逆时针旋转 \(90\) 度。
直线型水管是指左图里中间一行的两种水管。
现给出一个初始局面,请问最少进行多少次操作可以使棋盘上不存在漏水的地方。
输入格式
第一行两个正整数 \(n,m\),代表网格的大小。
接下来 \(n\) 行每行 \(m\) 个数,每个数是 \([0,15]\) 中的一个,你可以将其看作一个 \(4\) 位的二进制数,从低到高每一位分别代表初始局面中这个格子上、右、
下、左方向上是否有 水管接头。
特别地,如果这个数是 \(0\),则意味着这个位置没有水管。
比如 \(3(0011_{(2)})\) 代表上和右有接头,也就是一个 L 型,而 \(12(1100_{(2)})\) 代表下和左有接头,也就是将 L 型旋转 \(180\) 度。
输出格式
输出共一行,表示最少操作次数。如果无法达成目标,输出 \(-1\).
数据范围与提示
\(n \times m \le 2000\)
好神仙啊!
大致思路就是用一个水管的旋转代替所有水管的旋转。
代码:
#include<bits/stdc++.h>
#define ll long long
#define N 10005
using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
int n,m;
struct road {
int to,next;
int flow,cost;
}s[N*200];
int h[N],cnt=1;
void add(int i,int j,int f,int c) {
s[++cnt]=(road) {j,h[i],f,c};h[i]=cnt;
s[++cnt]=(road) {i,h[j],0,-c};h[j]=cnt;
}
int S,T;
int dis[N];
queue<int>q;
int e[N],fr[N];
bool in[N];
int ans,maxflow;
bool spfa() {
memset(dis,0x3f,sizeof(dis));
dis[S]=0;
q.push(S);
while(!q.empty()) {
int v=q.front();
q.pop();
in[v]=0;
for(int i=h[v];i;i=s[i].next) {
int to=s[i].to;
if(s[i].flow&&dis[to]>dis[v]+s[i].cost) {
dis[to]=dis[v]+s[i].cost;
fr[to]=v;
e[to]=i;
if(!in[to]) in[to]=1,q.push(to);
}
}
}
if(dis[T]>1e9) return 0;
for(int i=T;i!=S;i=fr[i]) {
s[e[i]].flow--;
s[e[i]^1].flow++;
}
maxflow++;
ans+=dis[T];
return 1;
}
vector<int>pipe;
int tot;
int ID[2005][2005][5];
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
int mp[2005][2005];
int main() {
n=Get(),m=Get();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
mp[i][j]=Get();
T=n*m+1;
tot=T;
int lpipe=0,rpipe=0;
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
int id=(i-1)*m+j;
int a=mp[i][j];
pipe.clear();
for(int k=0;k<4;k++) if(a>>k&1) pipe.push_back(k);
for(int k=0;k<4;k++) ID[i][j][k]=++tot;
if(i+j&1) {
lpipe+=pipe.size();
add(S,id,pipe.size(),0);
for(int k=0;k<pipe.size();k++) add(id,ID[i][j][pipe[k]],1,0);
if(a==10||a==5||a==15) continue ;
if(pipe.size()==1) {
int now=pipe[0];
add(ID[i][j][now],ID[i][j][(now+1)%4],1,1);
add(ID[i][j][now],ID[i][j][(now+2)%4],1,2);
add(ID[i][j][now],ID[i][j][(now+3)%4],1,1);
} else if(pipe.size()==2) {
for(int k=0;k<pipe.size();k++) {
int now=pipe[k];
add(ID[i][j][now],ID[i][j][(now+2)%4],1,1);
}
} else if(pipe.size()==3) {
int now;
for(int k=0;k<4;k++) if(!(a>>k&1)) now=k;
for(int k=0;k<3;k++) {
if((pipe[k]+2)%4==now) add(ID[i][j][pipe[k]],ID[i][j][now],1,2);
else add(ID[i][j][pipe[k]],ID[i][j][now],1,1);
}
}
} else {
rpipe+=pipe.size();
add(id,T,pipe.size(),0);
for(int k=0;k<pipe.size();k++) add(ID[i][j][pipe[k]],id,1,0);
if(a==10||a==5||a==15) continue ;
if(pipe.size()==1) {
int now=pipe[0];
add(ID[i][j][(now+1)%4],ID[i][j][now],1,1);
add(ID[i][j][(now+2)%4],ID[i][j][now],1,2);
add(ID[i][j][(now+3)%4],ID[i][j][now],1,1);
} else if(pipe.size()==2) {
for(int k=0;k<pipe.size();k++) {
int now=pipe[k];
add(ID[i][j][(now+2)%4],ID[i][j][now],1,1);
}
} else if(pipe.size()==3) {
int now;
for(int k=0;k<4;k++) if(!(a>>k&1)) now=k;
for(int k=0;k<3;k++) {
if((pipe[k]+2)%4==now) add(ID[i][j][now],ID[i][j][pipe[k]],1,2);
else add(ID[i][j][now],ID[i][j][pipe[k]],1,1);
}
}
}
}
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
if(i+j&1) {
for(int d=0;d<4;d++) {
int X=i+dx[d],Y=j+dy[d];
if(1<=X&&X<=n&&1<=Y&&Y<=m) {
add(ID[i][j][d],ID[X][Y][(d+2)%4],1,0);
}
}
}
}
}
if(lpipe!=rpipe) cout<<-1;
else {
while(spfa());
if(maxflow!=lpipe) cout<<-1;
else cout<<ans;
}
return 0;
}
Loj #2321. 「清华集训 2017」无限之环的更多相关文章
- UOJ #2321. 「清华集训 2017」无限之环
首先裂点表示四个方向 一条边上都有插头或者都不有插头,相当于满足流量平衡 最大流 = 插头个数*2时有解 然后求最小费用最大流 黑白染色分别连原点汇点
- LOJ2321. 「清华集训 2017」无限之环【费用流】
LINK 很好的一道网络里题 首先想插头DP的还是出门左转10分代码吧 然后考虑怎么网络流 首先要保证没有漏水 也就是说每个接口一定要有对应的接口 那么发现每个点只有可能和上下左右四个点产生联通关系 ...
- [LOJ#2330]「清华集训 2017」榕树之心
[LOJ#2330]「清华集训 2017」榕树之心 试题描述 深秋.冷风吹散了最后一丝夏日的暑气,也吹落了榕树脚下灌木丛的叶子.相识数年的Evan和Lyra再次回到了小时候见面的茂盛榕树之下.小溪依旧 ...
- [LOJ#2329]「清华集训 2017」我的生命已如风中残烛
[LOJ#2329]「清华集训 2017」我的生命已如风中残烛 试题描述 九条可怜是一个贪玩的女孩子. 这天她在一堵墙钉了 \(n\) 个钉子,第 \(i\) 个钉子的坐标是 \((x_i,y_i)\ ...
- Loj #2331. 「清华集训 2017」某位歌姬的故事
Loj #2331. 「清华集训 2017」某位歌姬的故事 IA 是一名会唱歌的女孩子. IOI2018 就要来了,IA 决定给参赛选手们写一首歌,以表达美好的祝愿.这首歌一共有 \(n\) 个音符, ...
- Loj #2324. 「清华集训 2017」小 Y 和二叉树
Loj #2324. 「清华集训 2017」小 Y 和二叉树 小Y是一个心灵手巧的OIer,她有许多二叉树模型. 小Y的二叉树模型中,每个结点都具有一个编号,小Y把她最喜欢的一个二叉树模型挂在了墙上, ...
- Loj 2320.「清华集训 2017」生成树计数
Loj 2320.「清华集训 2017」生成树计数 题目描述 在一个 \(s\) 个点的图中,存在 \(s-n\) 条边,使图中形成了 \(n\) 个连通块,第 \(i\) 个连通块中有 \(a_i\ ...
- [LOJ#2328]「清华集训 2017」避难所
[LOJ#2328]「清华集训 2017」避难所 试题描述 "B君啊,你当年的伙伴都不在北京了,为什么你还在北京呢?" "大概是因为出了一些事故吧,否则这道题就不叫避难所 ...
- [LOJ#2327]「清华集训 2017」福若格斯
[LOJ#2327]「清华集训 2017」福若格斯 试题描述 小d是4xx9小游戏高手. 有一天,小d发现了一个很经典的小游戏:跳青蛙. 游戏在一个 \(5\) 个格子的棋盘上进行.在游戏的一开始,最 ...
随机推荐
- WebSocket刨根问底(三)之群聊
前两篇文章[WebSocket刨根问底(一)][WebSocket刨根问底(二)]我们介绍了WebSocket的一些基本理论,以及一个简单的案例,那么今天继续,我们来看一个简单的群聊的案例,来进一步了 ...
- java基础4:深入理解final关键字
本文主要介绍了final关键字的使用方法及原理 具体代码在我的GitHub中可以找到 https://github.com/h2pl/MyTech 文章首发于我的个人博客: https://h2pl. ...
- 冗余jar包识别神器 - loose.jar
冗余jar包识别神器 - loose.jar 场景描述 项目迭代久了,会添加各类jar包,事实上很多jar包其实根本没用到.那如何快速识别冗余的jar,以方便从项目中清除掉呢? 比如: 该简单的测试工 ...
- 【转载】ASP.NET Core Web 支付功能接入 微信-扫码支付篇
转自:http://www.cnblogs.com/essenroc/p/8630730.html 这篇文章将介绍ASP.NET Core中使用 开源项目 Payment,实现接入微信-扫码支付及异步 ...
- 深度学习入门实战(一):像Prisma一样算法生成梵高风格画像
本文由云+社区发表 作者:董超 导语:现在人工智能是个大热点,而人工智能离不开机器学习,机器学习中深度学习又是比较热门的方向,本系列文章就从实战出发,介绍下如何使用MXnet进行深度学习~ 既然是实战 ...
- MySQL数据库实用技巧
1.如何快速掌握MySQL? 培养兴趣 兴趣是最好的老师,不论学习什么知识,兴趣都可以极大地提高学习效率.当然学习MySQL 5.6也不例外.夯实基础 计算机领域的技术非常强调基础,刚开始学习可能还认 ...
- 为容器化的 Go 程序搭建 CI
本文介绍如何使用 Jenkins 的声明式 pipeline 为一个简单的 Golang web 应用搭建 CI 环境.如果你还不太了解 Jenkins 及其声明式 pipeline,请先参考笔者的 ...
- java中变量的存储位置
1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符 ...
- IO通信模型(二)同步非阻塞模式NIO(NonBlocking IO)
同步非阻塞模式(NonBlocking IO) 在非阻塞模式中,发出Socket的accept()和read()操作时,如果内核中的数据还没有准备好,那么它并不会阻塞用户进程,而是立刻返回一个信息.也 ...
- React事件杂记及源码分析
前提 最近通过阅读React官方文档的事件模块,发现了其主要提到了以下三个点 调用方法时需要手动绑定this React事件是一种合成事件SyntheticEvent,什么是合成事件? 事件属性 ...