【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 ...
随机推荐
- 右键添加git-bash
主要: 右键如果没有git-bash,如何给右键手动添加 前面对右键存在git-bash但使用出现问题的解决,也想到如果右键都没有,该如何给右键添加了,于是接着记录下如何添加的过程: 情形: 手动给右 ...
- 自定义控件,继承自 ListView
public class MyListView extends ListView { /** * 如果在xml中创建并设置了style,就会调用三个参数的. * * @param context * ...
- 04 mysql 基础三 (进阶)
mysql 基础三 阶段一 mysql 单表查询 1.查询所有记录 select * from department; select * from student; select * from ...
- labview初始学习过程中遇到串口读取框红蓝色交替闪烁的处理
labview工程的程序框图VISA串口读取框红蓝交替闪烁,前面板接收数据错乱,或者是接受不了,这是你不小心设置了断点.
- SQL 公用表表达式(CTE)
1.概念 公用表表达式(Common Table Expression)是SQL SERVER 2005版本之后引入的一个特性.CTE可以看作是一个临时的结果集,可以在接下来的一个SELECT,INS ...
- Django-modelfrom组件
ModelForm a. class Meta: model, # 对应Model的 fi ...
- Bootstrap4用法
#Bootstrap4 ## 网格系统- .col- 针对所有设备- .col-sm- 平板 - 屏幕宽度等于或大于 576px- .col-md- 桌面显示器 - 屏幕宽度等于或大于 768px)- ...
- How to Upload multiple files to documentLibrary in one time
In a Sharepoint 2013 website,we can upload one file to the documentlibrary by click "Uploa ...
- howto:在构建基于debian的docker基础镜像时,更换国内包源
debian经常被用作构建应用镜像的基础镜像,如微软在构建linux下的dotnetcore基础镜像时,提供了基于debian 8(jessie)和debian 9(stretch)的镜像. 由于这些 ...
- 【BZOJ 1269】文本编辑器
题目 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对"文本编辑器"做了一个抽象的定义: Move k:将 ...