【BZOJ-4213】贪吃蛇 有上下界的费用流

时间:2021-09-16 03:08:27

4213: 贪吃蛇

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 58  Solved: 24
[Submit][Status][Discuss]

Description

 最近lwher迷上了贪吃蛇游戏,在玩了几天却从未占满全地图的情况下,他不得不承认自己是一个弱菜,只能改去开发一款更弱的贪吃蛇游戏。
在开发的过程中,lwher脑洞大开,搞了一个多条蛇的模式。但由于这种模式太难操作,于是他只好改变游戏的玩法,稍微变化一下游戏目标。
新的游戏是这样的:
一些蛇覆盖了一个网格。每个格子要么是一个障碍物,要么是蛇的一部分。每条蛇占据了一条折线(拐角处只能水平和竖直连接),且只是占据两个格子。蛇与蛇之间不能重叠,蛇也不会与自己重叠。每条蛇还必须满足以下两个条件中的一个:
     1、两个端点所在的格子在网格的边界。
     2、蛇构成一个环,即两个端点相邻(垂直或水平,不能斜着),至少要占据4个格子(否则没法形成环)。
给定一个网格,用r x c的字符矩阵描述:‘#’代表障碍物,‘.’代表空地。在满足前面所述的条件下覆盖所有空地,并使得端点在网格边界(即不构成环)的蛇尽量少。(如果一条蛇既构成环,又是端点在边界,那么不计入答案)
     例如,以下网格:
 
 【BZOJ-4213】贪吃蛇      有上下界的费用流
 
可以由下面三种方案覆盖。还有其他的方案,但是没法仅用一条不构成环的蛇就覆盖整个网络的方案。
【BZOJ-4213】贪吃蛇      有上下界的费用流
 
给定一个网络的描述,输出最少需要多少条不构成环的蛇来覆盖这个网格。如果不存在能够覆盖网格的方案,输出-1。

Input

一个字符矩阵,行数和列数不超过12。输入文件中没有多余的空白字符,每行之后都有换行符。

Output

输出满足题目要求的那个整数。

Sample Input

......
.#.##.
.#....
....#.
.##.#.
......

Sample Output

2

HINT

Source

Solution

感觉是插头DP或者费用流...立马把插头DP否了

网格基本上得先黑白染色

感觉环状蛇中每个点一定与两个点相连,非环蛇只有头尾不合两个点相连,所以实际上要算的就是和一个点相连的

S-->白点,容量2 : 上下界都是2  费用为0

黑点-->T,容量2:  上下界都是2  费用同样为0

表示这个点需要和别的两个点相连

然后白点向四周黑点扩展出一条边  容量为1 费用为0

这样就是环状蛇的建图(显然环蛇不计入答案,所以费用全部置成0)

然后特判边界情况,边界上的白点-->T   费用1 容量1 表示非环蛇的情况

然后跑上下界最小费用流,ans/2即为答案,因为非环蛇的头尾都被累计,相当于1条蛇贡献2,所以除二即可

上下界最小费用流?理论什么的忘记了。。。

实现起来就是用超级源汇替代原来的源汇,再由次级汇连次级源INF,然后跑超级源汇之间的费用流

无解按照特有判定,S出来的边应该全都满流,否则无解

Code

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
inline int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define MAXM 100010
#define MAXN 10010
int N,M,cas;
#define mN 15
#define mM 15
char G[mN][mM];
struct EdgeNode{int next,to,cap,cost;}edge[MAXM];
int head[MAXN],cnt=;
inline void AddEdge(int u,int v,int w,int c) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].cap=w; edge[cnt].cost=c;}
inline void InsertEdge(int u,int v,int w,int c) {AddEdge(u,v,w,c); AddEdge(v,u,,-c);}
int dis[MAXN],S,T,s,t,MinCost; bool mark[MAXN];
#define INF 0x7fffffff
bool spfa()
{
queue<int>q; memset(mark,,sizeof(mark));
for (int i=S; i<=T; i++) dis[i]=INF;
q.push(T); dis[T]=; mark[T]=;
while (!q.empty())
{
int now=q.front(); q.pop(); mark[now]=;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i^].cap && dis[edge[i].to]>dis[now]+edge[i^].cost)
{
dis[edge[i].to]=dis[now]+edge[i^].cost;
if (!mark[edge[i].to])
q.push(edge[i].to),mark[edge[i].to]=;
}
}
return dis[S]!=INF;
}
int dfs(int loc,int low)
{
mark[loc]=;
if (loc==T) return low;
int w,used=;
for (int i=head[loc]; i; i=edge[i].next)
if (edge[i].cap && !mark[edge[i].to] && dis[edge[i].to]==dis[loc]-edge[i].cost)
{
w=dfs(edge[i].to,min(low-used,edge[i].cap));
edge[i].cap-=w; edge[i^].cap+=w; used+=w; MinCost+=w*edge[i].cost;
if (used==low) return low;
}
return used;
}
int zkw()
{
int tmp=;
while (spfa())
{
mark[T]=;
while (mark[T])
memset(mark,,sizeof(mark)),tmp+=dfs(S,INF);
}
return tmp;
}
bool Judge() {bool f=; for (int i=head[S]; i; i=edge[i].next) if (edge[i].cap) {f=;break;} return !f;}
inline bool Check(int x,int y) {if (x>= && x<=N && y>= && y<=M && G[x][y]!='#') return ; return ;}
int D[mN*mM],id[mN][mM],col[mN][mM];
void BuildGraph()
{
S=; T=N*M+; s=N*M+; t=N*M+; int idd=;
for (int i=; i<=N; i++)
for (int j=; j<=M; j++)
id[i][j]=++idd,col[i][j]=(i+j)&;
for (int i=; i<=N; i++)
for (int j=; j<=M; j++)
if (col[i][j])
if (Check(i,j)) D[s]-=,D[id[i][j]]+=; else;
else
if (Check(i,j)) D[id[i][j]]-=,D[t]+=; else;
for (int i=; i<=N; i++)
for (int j=; j<=M; j++)
if (col[i][j] && Check(i,j))
{
if (Check(i-,j)) InsertEdge(id[i][j],id[i-][j],,);
if (Check(i,j-)) InsertEdge(id[i][j],id[i][j-],,);
if (Check(i+,j)) InsertEdge(id[i][j],id[i+][j],,);
if (Check(i,j+)) InsertEdge(id[i][j],id[i][j+],,);
}
for (int i=; i<=N; i++)
for (int j=; j<=M; j++)
if (i== || i==N || j== || j==M)
if (col[i][j])
if (Check(i,j)) InsertEdge(id[i][j],t,,); else;
else
if (Check(i,j)) InsertEdge(s,id[i][j],,); else;
for (int i=; i<=t; i++)
if (D[i]>) InsertEdge(S,i,D[i],);
else
if (D[i]<) InsertEdge(i,T,-D[i],);
InsertEdge(t,s,INF,);
}
int tp;
int main()
{
tp=; while (scanf("%s",G[tp]+)!=EOF) tp++;
N=tp-,M=strlen(G[]+);
BuildGraph();
zkw();
if (Judge()) {puts("-1"); return ;}
printf("%d\n",MinCost>>);
return ;
}

什么垃圾读入方式,恶心!

【BZOJ-4213】贪吃蛇 有上下界的费用流的更多相关文章

  1. 【UVALive - 5131】Chips Challenge(上下界循环费用流)

    Description A prominent microprocessor company has enlisted your help to lay out some interchangeabl ...

  2. BZOJ 4213 贪吃蛇 上下界费用流 网络流

    https://darkbzoj.cf/problem/4213 https://www.cnblogs.com/DaD3zZ-Beyonder/p/5733326.html 题目描述 dbzoj又崩 ...

  3. BZOJ 2055&colon; 80人环游世界&lpar;有上下界的费用流&rpar;

    题面 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 693 Solved: 434 [Submit][Status][Discuss] Descript ...

  4. BZOJ2055 80人环游世界 网络流 费用流 有源汇有上下界的费用流

    https://darkbzoj.cf/problem/2055 https://blog.csdn.net/Clove_unique/article/details/54864211 ←对有上下界费 ...

  5. BZOJ 3876&colon; &lbrack;Ahoi2014&rsqb;支线剧情 带下界的费用流

    3876: [Ahoi2014]支线剧情 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=3876 Description [故事背景] 宅 ...

  6. Codeforces Gym 101190 NEERC 16 &period;D Delight for a Cat (上下界的费用流)

    ls是一个特别堕落的小朋友,对于n个连续的小时,他将要么睡觉要么打隔膜,一个小时内他不能既睡觉也打隔膜 ,因此一个小时内他只能选择睡觉或者打隔膜,当然他也必须选择睡觉或打隔膜,对于每一个小时,他选择睡 ...

  7. 【上下界网络流 费用流】bzoj2055&colon; 80人环游世界

    EK费用流居然写错了…… Description     想必大家都看过成龙大哥的<80天环游世界>,里面的紧张刺激的打斗场面一定给你留下了深刻的印象.现在就有这么     一个80人的团 ...

  8. UvaL-7670 上下界可行费用流

    #include <iostream> #include <cstdio> #include <cstring> #include <queue> #d ...

  9. BZOJ 3876 支线剧情 有源汇有上下界最小费用可行流

    题意: 给定一张拓扑图,每条边有边权,每次只能从第一个点出发沿着拓扑图走一条路径,求遍历所有边所需要的最小边权和 分析: 这道题乍一看,可能会想到什么最小链覆盖之类的,但是仔细一想,会发现不行,一是因 ...

随机推荐

  1. Unity 重要基础知识点

    这是两个月前的学习记录,发出来了下,如果有误欢迎大家指出: 脚本生命周期 //每当脚本被加载时调用一次 // 1.   在Awake中做一些初始化操作 void Awake(){ //初始化publi ...

  2. html5离线应用和缓存

    1 localstorage和sessionstorage sessionStrage: session即会话的意思,在这里的session是指用户浏览某个网站时,从进入网站到关闭网站这个时间段,se ...

  3. 数据存储--sqlite总结

    SQLite SQLite(轻量级的数据库,关系型数据库) 辅助工具:Navicat Premium 等 原理:ios针对存储问题封装了sqlite数据库(c语言数据库). 1 app获取沙盒地址命名 ...

  4. PHP时间比较和时间差如何计算

    1.<?php 2. $zero1=date(“y-m-d h:i:s”); 3. $zero2=”2010-11-29 21:07:00′; 4. echo “zero1的时间为:”.$zer ...

  5. Count属性(行数 &commat;)

    在PS2.0中,如果返回值为空,则count也会返回空(vm.txt内容为空),如下: (gc d:\vm.txt).count 如果加上@的话,会返回0 @(gc d:\vm.txt).count ...

  6. cellForRowAtIndexPath方法不执行的那些坑

    今天用到了uitableview,是xib形式的.不过cellForRowAtIndexPath方法死活不执行,检查了返回的row数量,section的数量,数据源,代理都没问题,不过cellForR ...

  7. ef code first

    , 网上有很多的ef  code first 的使用的方式,很乱,下面是我自己整理出来的,有什么不正确的地方还请指正,本人菜鸟一枚! 1.新建一个类库 =>引用 右击 管理NuGet程序包 添加 ...

  8. 常见的Mysql数据库优化总结

    索引 1.主键索引 作用:唯一约束和提高查询速度 #建表时创建主键索引 create table `table_name`( `id` int unsigned not null auto_incre ...

  9. &lbrack;20190319&rsqb;shared pool latch与library cache latch的简单探究&period;txt

    [20190319]shared pool latch与library cache latch的简单探究.txt --//昨天看Oracle DBA手记3:数据库性能优化与内部原理解析.pdf 电子书 ...

  10. Java语法基础学习DayEighteen(常用类)

    一.String类 1.特点 String代表不可变的字符序列,底层用char[]存放. String是final的. 2.内存解析 3.常用方法 int length() char charAt(i ...