【bzoj2756 奇怪的游戏】
Time Limit: 40 Sec Memory Limit: 128 MB
Submit: 4403 Solved: 1226
[Submit][Status][Discuss]
Description
Blinker最近喜欢上一个奇怪的游戏。
这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数。每次 Blinker 会选择两个相邻
的格子,并使这两个数都加上 1。
现在 Blinker 想知道最少多少次能使棋盘上的数都变成同一个数,如果永远不能变成同
一个数则输出-1。
Input
输入的第一行是一个整数T,表示输入数据有T轮游戏组成。
每轮游戏的第一行有两个整数N和M, 分别代表棋盘的行数和列数。
接下来有N行,每行 M个数。
Output
对于每个游戏输出最少能使游戏结束的次数,如果永远不能变成同一个数则输出-1。
Sample Input
2 2
1 2
2 3
3 3
1 2 3
2 3 4
4 3 2
Sample Output
-1
HINT
【数据范围】
对于30%的数据,保证 T<=10,1<=N,M<=8
对于100%的数据,保证 T<=10,1<=N,M<=40,所有数为正整数且小于1000000000
Source
【题解】
①你有一个很好的愿望:要是能知道最后的棋盘是什么样子就好了!
②设棋盘最后都为x(同时和数与形状相关的问题,染色很实用),
染色后设白格总数num1,和sum1;黑格总数num2,和sum2;我们可以写下这样的式子:
x*num1-sum1=x*num2-sum2 (由于选取相邻的两个格+1) 化一化:
sum1-sum2=x*(num1-num2) 回到初中学过的一元一次方程解的讨论:
若num1-num2≠0 ,解出x,若比原图中maxn还小,就一定不行,反之check一下;
若num1-num2=0,若sum1-sum2≠0肯定就没戏了,反之就此方程对应了很多很多解,考虑实际情况我们可以说在这种情况下:x取a成立的话,取a+1一定成立(但是对a和a-1就不一定对了,我就是错在这里的),二分+check即可;
③check的话就超源连白色,超汇连黑色,边为差值,对白格向相邻黑格建inf边,看是否满流。
/*2
2 2
1 2
2 3
3 3
1 2 3
2 3 4
4 3 2
没去freopen居然调了半个小时,醉了。
inf和INF什么的,最讨厌了。
染色技巧很玄妙!
*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <ctime>
#include <cmath>
#define ll long long
#define N 50
#define mem(f,a) memset(f,a,sizeof(f))
#define Run(i,l,r) for(ll i=l;i<=r;i++)
#define Don(i,l,r) for(ll i=l;i>=r;i--)
#define Eun(i,u,E,head) for(ll i=head[u],v=E[i].v;i!=-1;i=E[i].next,v=E[i].v)
using namespace std;
int n,m;
const ll inf=(1LL<<);
const ll INF=(1LL<<);
struct Edge{
int v,next;
ll cap,flow;
}E[];
ll a[N][N],color[N][N];
ll head[N*N],k,cur[N*N],vis[N*N],d[N*N];
int dx[]={,,,-},dy[]={,-,,};
queue<int>q;
int idx(int i,int j){return (i-)*m+j;}
void adde(int u,int v,ll cap)
{ E[k]=(Edge){v,head[u],cap,};
head[u]=k++;
E[k]=(Edge){u,head[v],,};
head[v]=k++;
}
bool Bfs()
{ mem(vis,); mem(d,);
vis[]=; q.push();
while (!q.empty()){
int u=q.front(); q.pop();
Eun(i,u,E,head)if (E[i].cap>E[i].flow&&!vis[v]){
vis[v]=;
q.push(v);
d[v]=d[u]+;
}
}
return (vis[n*m+]);
}
ll Dfs(int u,ll a)
{ if (u==n*m+||a==) return a;
ll flow=,f;
Eun(i,u,E,cur){
cur[u]=i;
if (d[v]==d[u]+&&(f=Dfs(v,min(E[i].cap-E[i].flow,a)))>){
flow+=f;
a-=f;
E[i].flow+=f;
E[i^].flow-=f;
}
if (a==) break;
}
return flow;
}
ll Dinic()
{ ll flow=;
while (Bfs()){
Run(i,,n*m+) cur[i]=head[i];
flow+=Dfs(,INF);
}
return flow;
}
bool check(ll x)
{ k=; mem(head,-);
ll tot=;
Run(i,,n)
Run(j,,m){
if (color[i][j]) {
tot+=x-a[i][j];
adde(,idx(i,j),x-a[i][j]);
Run(k,,){
int ni=i+dx[k]; int nj=j+dy[k];
if (ni>&&nj>&&ni<=n&&nj<=m) adde(idx(i,j),idx(ni,nj),INF);
}
}
else adde(idx(i,j),n*m+,x-a[i][j]);
}
if (tot==Dinic()) return ;
else return ;
}
int main()
{ freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
int T;
scanf("%d",&T);
while (T--){
scanf("%d%d",&n,&m);
ll maxn=,num1=,num2=; ll sum1=,sum2=;
Run(i,,n)
Run(j,,m){
scanf("%lld",&a[i][j]);
maxn=max(maxn,a[i][j]);
if ((i+j)&) color[i][j]=,sum1+=a[i][j],num1++;
else color[i][j]=,sum2+=a[i][j],num2++;
}
if (num1==num2) {
if (sum1!=sum2) {printf("-1\n"); continue;}
ll l=maxn,r=inf,x=;
while (l<r){
ll mid=(l+r)/;
if (check(mid)) x=mid,r=mid;
else l=mid+;
}
if (x) printf("%lld\n",1ll*x*num1-sum1);
else printf("-1\n");
}
else {
ll temp=(sum1-sum2)/(num1-num2);
if (temp>=maxn&&check(temp)) printf("%lld\n",1ll*temp*num1-sum1);
else printf("-1\n");
}
}
return ;
}//by tkys_Austin;
【bzoj2756 奇怪的游戏】的更多相关文章
- BZOJ-2756 奇怪的游戏 黑白染色+最大流+当前弧优化+二分判断+分类讨论
这个题的数据,太卡了,TLE了两晚上,各种调试优化,各种蛋疼. 2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MB Submit ...
- [bzoj2756]奇怪的游戏
对棋盘黑白染色后,若n和m都是奇数(即白色和黑色点数不同),可以直接算得答案(根据白-黑不变):若n和m不都是奇数,二分答案(二分的上限要大一点,开$2^50$),最后都要用用网络流来判定.考虑判定, ...
- 【BZOJ2756】奇怪的游戏(二分,最小割)
题意: Blinker最近喜欢上一个奇怪的游戏.这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻的格子,并使这两个数都加上 1.现在 Blinker 想知道最 ...
- 【BZOJ2756】奇怪的游戏(二分,网络流)
[BZOJ2756]奇怪的游戏(二分,网络流) 题面 BZOJ Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blink ...
- 【BZOJ-2756】奇怪的游戏 最大流 + 分类讨论 + 二分
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 2925 Solved: 792[Submit][Stat ...
- Bzoj2756 [SCOI2012]奇怪的游戏
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 3220 Solved: 886 Description ...
- BZOJ2756:[SCOI2012]奇怪的游戏(最大流,二分)
Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻 的格子,并使这两个数都加上 1. 现在 B ...
- BZOJ2756 [SCOI2012]奇怪的游戏 【网络流 + 二分】
题目 Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻 的格子,并使这两个数都加上 1. 现在 Blinker 想知 ...
- bzoj2756: [SCOI2012]奇怪的游戏(网络流+分情况)
2756: [SCOI2012]奇怪的游戏 题目:传送门 题解: 发现做不出来的大难题一点一个网络流 %大佬 首先黑白染色(原来是套路...)染色之后就可以保证每次操作都一定会使黑白各一个各自的值加1 ...
随机推荐
- redis搭建
redis 1.简介.安装 Remote Dictionary Server(Redis)是一个基于 key-value 键值对的持久化数据库存储系统.redis 和 Memcached 缓存服务很像 ...
- Hadoop(24)-Hadoop优化
1. MapReduce 跑得慢的原因 优化方法 MapReduce优化方法主要从六个方面考虑:数据输入.Map阶段.Reduce阶段.IO传输.数据倾斜问题和常用的调优参数. 数据输入 Map阶段 ...
- spring-boot整合ehcache实现缓存机制
EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider. ehcache提供了多种缓存策略,主要分为内存和磁盘两级,所以无需担心 ...
- Teen Readers【青少年读者】
Teen Readers Teens and younger children are reading a lot less for fun, according to a Common Sense ...
- Ubuntu无法安装vim怎么办?(Ubuntu 出现apt-get: Package has no installation candidate问题)
apt-get install vim 正在读取软件包列表... 完成 正在分析软件包的依赖关系树 正在读取状态信息... 完成 有一些软件包无法被安装.如果您用的是不稳定(unstable)发行版, ...
- 扩展报表-JavaSet
前言 使用商业分析中的扩展报表平台,可以很方便的进行数据分析,进行图表化直观展示.一般情况下使用SQL数据集进行SQL的编写,进而配合扩展报表平台进行数据分析图表的绘制,但SQL数据集针对固定的参数进 ...
- struts2官方 中文教程 系列七:消息资源文件
介绍 在本教程中,我们将探索使用Struts 2消息资源功能(也称为 resource bundles 资源绑定).消息资源提供了一种简单的方法,可以将文本放在一个视图页面中,通过应用程序,创建表单字 ...
- 3106: [cqoi2013]棋盘游戏
3106: [cqoi2013]棋盘游戏 链接 分析: 极大极小搜索 + 记忆化. 代码 #include<bits/stdc++.h> using namespace std; type ...
- java容器操作一
List l = new ArrayList(); l.add(1); l.add("ne"); // 获取 System.out.println(l.get(0)); // 判断 ...
- 添加用户-查看用户列表-禁止默认root登陆
程序小屌丝狒狒: (Q971751392) linux添加用户 adduser feifei passwd [用户名] 设置密码 可以查看所有用户的列表 cat /etc/passwd w 可以查看 ...