bzoj4213 贪吃蛇
来源:互联网 发布:办公室椅子知乎 编辑:程序博客网 时间:2024/06/05 19:32
原blog
Description
最近lwher迷上了贪吃蛇游戏,在玩了几天却从未占满全地图的情况下,他不得不承认自己是一个弱菜,只能改去开发一款更弱的贪吃蛇游戏。
在开发的过程中,lwher脑洞大开,搞了一个多条蛇的模式。但由于这种模式太难操作,于是他只好改变游戏的玩法,稍微变化一下游戏目标。
新的游戏是这样的:
一些蛇覆盖了一个网格。每个格子要么是一个障碍物,要么是蛇的一部分。每条蛇占据了一条折线(拐角处只能水平和竖直连接),且只是占据两个格子。蛇与蛇之间不能重叠,蛇也不会与自己重叠。每条蛇还必须满足以下两个条件中的一个:
1、两个端点所在的格子在网格的边界。
2、蛇构成一个环,即两个端点相邻(垂直或水平,不能斜着),至少要占据4个格子(否则没法形成环)。
给定一个网格,用r x c的字符矩阵描述:‘#’代表障碍物,‘.’代表空地。在满足前面所述的条件下覆盖所有空地,并使得端点在网格边界(即不构成环)的蛇尽量少。(如果一条蛇既构成环,又是端点在边界,那么不计入答案)
例如,以下网格:
可以由下面三种方案覆盖。还有其他的方案,但是没法仅用一条不构成环的蛇就覆盖整个网络的方案。
给定一个网络的描述,输出最少需要多少条不构成环的蛇来覆盖这个网格。如果不存在能够覆盖网格的方案,输出-1。
Input
一个字符矩阵,行数和列数不超过12。输入文件中没有多余的空白字符,每行之后都有换行符。
Output
输出满足题目要求的那个整数。
Sample Input
……
.#.##.
.#….
….#.
.##.#.
……
Sample Output
2
思路巧妙 这样的棋盘题有可能是插头dp 或者是什么染色完搞一搞匹配什么的 还是跪膜了zhx大佬的题解
集训队大爷leoly说不用费用流 0ms bzoj rank3
大概想法就是首先染个色 我们可以知道 互相连接的点一定在棋盘上属于不同的颜色 一个点被贯通 意味着他的度是2 因为要和周围的点连接嘛 然后如果只是一条链的话 那么度就是1 形成环的情况下是我们不用考虑的 只有形成链的时候我要计数 那么显然形成链的时候我无法跑满 使得每个点度为2 这时候正好添加费用为1的边即可解决
建图方法:首先 源向所有的白点连容量确切为2 的边 然后所有黑点向汇连容量确切为2的边 所有白点都可以向附近的黑点连容量为1 的下界为0的边 这时候万一不平衡 就需要我们带费用的边来弥补了 根据题意 只有当我在边界的时候才可能产生费用 那么就从源向黑点连容量1 费用1的边 从白点向汇连容量1 费用1的边 然后跑一下最小费用可行流即可 因为这个蛇大致在头尾的时候各被不可避免的算了费用 所以总费用需要/2
#include<queue>#include<cstdio>#include<cstring>#include<algorithm>#define inf 0x3f3f3f3f#define N 200using namespace std;char mp[N][N];int n,m,id[N][N],tot,dx[]={0,1,-1,0},dy[]={1,0,0,-1};int num=1,T,S,h[N<<1],flag[N<<1],f[N<<1],pre[N<<1],path[N<<1],d[N<<1];struct node{ int y,z,next,c;}data[N*4];inline void insert1(int x,int y,int z,int c){ data[++num].y=y;data[num].z=z;data[num].next=h[x];data[num].c=c;h[x]=num; data[++num].y=x;data[num].z=0;data[num].next=h[y];data[num].c=-c;h[y]=num; }int s,t;inline bool spfa(){ queue<int>q;memset(flag,0,sizeof(flag));memset(f,0x3f,sizeof(f));f[S]=0;flag[S]=1;memset(pre,-1,sizeof(pre));q.push(S); while(!q.empty()){ int x=q.front();q.pop();flag[x]=0; for (int i=h[x];i;i=data[i].next){ int y=data[i].y,z=data[i].z,c=data[i].c; if (f[x]+c<f[y]&&z){ f[y]=f[x]+c;pre[y]=x;path[y]=i; if (!flag[y]) flag[y]=1,q.push(y); } } }if (pre[T]==-1) return 0;else return 1;}int main(){ freopen("bzoj4213.in","r",stdin); while(~scanf("%s",mp[++n]+1));m=strlen(mp[1]+1);n--; for (int i=1;i<=n;++i) for (int j=1;j<=m;++j) if (mp[i][j]!='#') id[i][j]=++tot;s=0;t=tot+1;S=t+1;T=S+1; for (int i=1;i<=n;++i){ for (int j=1;j<=m;++j){ if (mp[i][j]=='#') continue; if ((i+j)%2==0){ d[s]-=2;d[id[i][j]]+=2; for (int k=0;k<4;++k){ int x1=i+dx[k],y1=j+dy[k]; if (x1<1||x1>n||y1<1||y1>m||mp[x1][y1]=='#') continue; insert1(id[i][j],id[x1][y1],1,0); } if (i==1||j==1||i==n||j==m) insert1(id[i][j],t,1,1); }else{ d[id[i][j]]-=2;d[t]+=2;if (i==1||j==1||i==n||j==m) insert1(s,id[i][j],1,1); } } }insert1(t,s,inf,0);int sum=0; for (int i=s;i<=t;++i) { if (d[i]<0) insert1(i,T,-d[i],0); if (d[i]>0) insert1(S,i,d[i],0),sum+=d[i]; }int ans=0,ans1=0; while(spfa()){ int minn=inf,now=T; while(now!=S) minn=min(minn,data[path[now]].z),now=pre[now];ans+=minn;now=T; while(now!=S){ans1+=data[path[now]].c*minn;data[path[now]].z-=minn;data[path[now]^1].z+=minn;now=pre[now];} }if (ans!=sum) {printf("-1");return 0;}printf("%d",ans1>>1); return 0;}
- bzoj4213 贪吃蛇
- 【bzoj4213】【贪吃蛇】【有上下界的费用流】
- bzoj4213 贪吃蛇(二分图染色+有源汇有上下界最小费用流)
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- Length of Last Word
- 《Java 编程技巧1001条》 第404条 了解实用方法
- bzoj 2199: [Usaco2011 Jan]奶牛议会
- C#基础知识简单梳理
- Cloudera Manager和CDH5.11.0升级流程
- bzoj4213 贪吃蛇
- 重构客户注册-基于ActiveMQ实现短信验证码生产者
- MongoDB的安装与配置
- binder原理
- 应用部署的六种策略
- JAVA实现约瑟夫环
- 【基础】 EFI基本概念之HOB
- 解决Failed to load class "org.slf4j.impl.StaticLoggerBinder"问题
- C语言printf()、sprintf()、vsprintf() 的区别与联系