bzoj 2756奇怪的游戏

2756: [SCOI2012]奇怪的游戏

Time Limit: 40 Sec  Memory Limit: 128 MB
Submit: 2571  Solved: 685
[Submit][Status][Discuss]

Description

Blinker最近喜欢上一个奇怪的游戏。 
这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数。每次 Blinker 会选择两个相邻
的格子,并使这两个数都加上 1。 
现在 Blinker 想知道最少多少次能使棋盘上的数都变成同一个数,如果永远不能变成同
一个数则输出-1。 

Input

输入的第一行是一个整数T,表示输入数据有T轮游戏组成。 
每轮游戏的第一行有两个整数N和M, 分别代表棋盘的行数和列数。 
接下来有N行,每行 M个数。 

Output


  对于每个游戏输出最少能使游戏结束的次数,如果永远不能变成同一个数则输出-1。

Sample Input

2
2 2
1 2
2 3
3 3
1 2 3
2 3 4
4 3 2

Sample Output

2
-1

HINT

 

【数据范围】 

    对于30%的数据,保证  T<=10,1<=N,M<=8 

对于100%的数据,保证  T<=10,1<=N,M<=40,所有数为正整数且小于1000000000 

 

考虑末状态有所有数都相等的很好性质,所以设所有数的变为x。因为每次只会对相邻两个格子加1,所以奇偶分治后,两种格子的变化量相同。

所以可以列出方程

这里借用黄学长的博客

对棋盘进行黑白染色
设黑格个数为num1 数值和为sum1
设白格个数为num1 数值和为sum1

设最后都变为x

num1 * x – sum1 = num2 * x – sum2
x = (sum1 – sum2) / (num1 – num2)

 

然后分类讨论

当num1 ≠ num2时 可以解出 x 再用网络流check即可

对于num1 = num2时 可以发现 对于一个合法的x k>=x都是一个合法的解
因为num1 = num2 => (num1 + num2) % 2 == 0 可以构造一层的满覆盖
所以可以二分x 然后用网络流check

建图:
如果点k为白
建边(s, k, x – v[k])
如果为黑
建边(k, t, x – v[k])
对相邻点u、v (u为白)
建边 (u, v, inf)

 

方法:利用末状态性质,设未知数,列出方程。然后分类讨论,首先要满足方程才有解,然后可以二分答案,在check。其实如果都合法,可以直接二分末状态,然后check。方程讨论是因为解得情况在不同条件下不同。

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 2020
#define maxm 8020
#define INF 100000000000000lltypedef long long LL;
struct node{int next,to;LL f;
}e[maxm * 2];
int head[maxn],cnt = 1,src,sink;
int q[maxn],hh,tt,dis[maxn],cur[maxn];
int n,m,T,num1,num2,mx;
LL sum1,sum2,maxflow,x,ans;
int dt[maxn][maxn];inline void adde(int x,int y,LL c){e[++cnt].to = y;e[cnt].next = head[x];e[cnt].f = c;head[x] = cnt;e[++cnt].to = x;e[cnt].next = head[y];head[y] = cnt;
}
inline bool bfs(){tt = hh = 0;memset(dis,0,sizeof(dis));q[tt++] = src , dis[src] = 1;while ( hh < tt ){int now = q[hh++];for (int i = head[now] ; i ; i = e[i].next){if ( e[i].f && !dis[e[i].to] ){q[tt++] = e[i].to;dis[e[i].to] = dis[now] + 1;}}}return dis[sink] > 0;
}
LL dfs(int now,LL delta){if ( now == sink || !delta ) return delta;LL ret = 0;for (int &i = cur[now] ; i ; i = e[i].next){if ( e[i].f && dis[now] + 1 == dis[e[i].to] ){LL d = dfs(e[i].to,min(delta,e[i].f));ret += d , delta -= d;e[i].f -= d, e[i ^ 1].f += d;if ( !delta ) return ret;}}if ( delta ) dis[now] = -1;return ret;
} 
inline LL dinic(){LL flow = 0;while ( bfs() ){for (int i = 1 ; i <= sink ; i++) cur[i] = head[i];flow += dfs(src,INF);}return flow;
}
inline void init(LL x){memset(head,0,sizeof(head));memset(e,0,sizeof(e));cnt = 1;for (int i = 1 ; i <= n ; i++){for (int j = 1 ; j <= m ; j++){if ( (i + j) & 1 ){adde((i - 1) * m + j,sink,x - (LL)dt[i][j]);}else{int now = (i - 1) * m + j;adde(src,(i - 1) * m + j,x - (LL)dt[i][j]);if ( i > 1 ) adde(now,now - m,INF);if ( i < n ) adde(now,now + m,INF);if ( j > 1 ) adde(now,now - 1,INF);if ( j < m ) adde(now,now + 1,INF);}}}
}
int main(){freopen("input.txt","r",stdin);scanf("%d",&T);while ( T-- ){ans = sum1 = sum2 = 0 , mx = num1 = num2 = 0;scanf("%d %d",&n,&m);src = n * m + 1 , sink = n * m + 2;for (int i = 1 ; i <= n ; i++){for (int j = 1 ; j <= m ; j++){scanf("%d",&dt[i][j]);if ( (i + j) & 1 ) sum2 += (LL)dt[i][j] , num2++;else sum1 += (LL)dt[i][j], num1++;mx = max(dt[i][j],mx);}}if ( num1 != num2 ){if ( ((sum1 - sum2) % (LL)(num1 - num2)) != 0 ){printf("-1\n");continue;}	x = (sum1 - sum2) / (LL)(num1 - num2);if ( x < mx ){printf("-1\n");continue;}init(x);maxflow = dinic();if ( maxflow + sum1 == (LL)num1 * x ){printf("%lld\n",maxflow);}else printf("-1\n");}else{LL l = mx , r = INF;//二分把当前的每个数都变成mid的情况for (int i = 1 ; i <= 50 ; i++){maxflow = 0;LL mid = (l + r) >> 1;init(mid);maxflow = dinic();if ( maxflow + sum1 == (LL) num1 * mid ){ans = maxflow , r = mid;}else l = mid + 1;}if ( !ans ) printf("-1\n");else printf("%lld\n",ans);}}return 0;
}

转载于:https://www.cnblogs.com/zqq123/p/5263783.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/396666.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

秒懂,Java 注解 (Annotation)你可以这样学

转自: https://blog.csdn.net/briblue/article/details/73824058 文章开头先引入一处图片。 这处图片引自老罗的博客。为了避免不必要的麻烦&#xff0c;首先声明我个人比较尊敬老罗的。至于为什么放这张图&#xff0c;自然是为本篇博文服务&#xff0c;接下来我自会说明。好了…

Java技术中的三大特性

为什么80%的码农都做不了架构师&#xff1f;>>> 1&#xff0e;虚拟机 Java虚拟机JVM&#xff08;Java Virtual Machine&#xff09;在Java编程里面具有非常重要的地位&#xff0c;约相当…

matlab图像增强分段线性函数_图像增强、锐化,利用 PythonOpenCV 来实现 4 种方法!...

图像增强目的使得模糊图片变得更加清晰、图片模糊的原因是因为像素灰度差值变化不大&#xff0c;图片各区域产生视觉效果似乎都是一样的&#xff0c; 没有较为突出的地方&#xff0c;看起来不清晰的感觉解决这个问题的最直接简单办法&#xff0c;放大像素灰度值差值、使图像中的…

python多人聊天室_Python基于Socket实现简易多人聊天室

前言套接字(Sockets)是双向通信信道的端点。 套接字可以在一个进程内&#xff0c;在同一机器上的进程之间&#xff0c;或者在不同主机的进程之间进行通信&#xff0c;主机可以是任何一台有连接互联网的机器。套接字可以通过多种不同的通道类型实现&#xff1a;Unix域套接字&…

计算机考研保护一志愿,考研良心大学,保护一志愿的考研名校!

大家好&#xff0c;我是&#xff0c;今天胖胖要跟大家送一些重要的干货&#xff0c;就是对于选学校的小伙伴来说也好&#xff0c;或者是即将要参加研究生复试的小伙伴们来好胖胖在这里要跟大家说一个关于考研白名单的事情&#xff0c;因为大家都知道考研是会分黑名单和白名单&a…

python变量输出到文件_使用函数将多个变量写入文件

首先&#xff0c;要获得当前正在执行的脚本名&#xff0c;或者更确切地说是调用函数的模块&#xff0c;必须从堆栈跟踪中获取它。globals()-它将在writeToValues()函数的相同上下文中执行&#xff0c;因此它不会从“调用者”接收globals()。要纠正这种情况&#xff0c;您可以使…

嵌入式linux系统移植的四大步骤_嵌入式系统移植步骤

在嵌入式系统移植中重要的一部分是操作系统的移植&#xff0c;与其它操作系统相比&#xff0c;Linux大的特点&#xff1a;它是一款遵循GPL的操作系统&#xff0c;我们可以自由地使用、修改、和扩展它。正是由于这一特色&#xff0c;嵌入式系统移植过程中Linux系统受到越来越多人…

sdn框架的计算机网络管理,清华SDN实践--SDN 系统架构与数据中心应用

清华大学在SDN 的系统架构以及其在数据中心网络中的应用方面展开了深入研究&#xff0c;主要研究成果包括&#xff1a;1. 以数据为中心的软件定义网络架构 SODA(Software Defined Data Centric Networking)。与 OpenFlow 相比&#xff0c;SODA 大大增强了数据层面的处理能力&am…

《软件工程》课之-调查问卷的心得体会

1.这次调查是艰辛的。 2.很多人都误以为我在发小广告。。 3.很多人都不认识俄罗斯方块1010这个游戏。 4.大家对于游戏的见解千奇百怪。 5.题目出的不是很完美&#xff0c;下次改进。。 6.简单分析下结果&#xff0c;男孩子都喜欢多人的游戏&#xff0c;女孩的喜欢的多种多样&am…

python循环语句for求和_for循环简介

## for循环简介for循环可以用来遍历某一对象(遍历&#xff1a;通俗点说&#xff0c;就是把这个循环中的第一个元素到最后一个元素依次访问一次)。for循环的基本结构如下&#xff1a;![](https://img.kancloud.cn/75/33/753371a9536ed9eeb159074482ec85f0_558x174.png)说明&…

华为备份历史版本_华为手机NAS备份时提示“需处于同一局域网”的解决方法

本内容来源于什么值得买APP&#xff0c;观点仅代表作者本人 &#xff5c;作者&#xff1a;噩梦飘雷创作立场声明&#xff1a;在使用华为手机向群晖NAS中备份时发现一直无法成功&#xff0c;经过一番研究找到了解决方案&#xff0c;希望能帮到大家~前言最近看了一位老哥的帖子&a…

计算机系统集成难点,企业MES实施中存在的难点及建议

MES是企业生产管理服务的核心信息化系统。实施MES是为了将现代企业生产管理思想、理念引入企业生产管理&#xff0c;对企业生产管理流程进行重组和优化&#xff0c;促进企业生产管理水平的提高。可是作用如此大的MES系统在实施过程中能一路无阻吗&#xff1f;MES系统的作用1.车…

【原创】自己编写的JavaGUI一键生成(hibernate/spring/mvc/maven)工具(附带视频教程源码)...

为什么80%的码农都做不了架构师&#xff1f;>>> 带项目源码&#xff08;https://git.oschina.net/qsyan/GeneratorFx&#xff09; app下载地址(附带视频教程)&#xff1a;http://download.csdn.net/detail/juyan2008/9769406 注明&#xff1a;此应用采用javafx编写…

2018-2019 20165203 《信息安全系统设计基础》第一周学习总结

2018-2019-1 20165203 《信息安全系统设计基础》第一周学习总结 教材学习内容总结 编译&#xff1a;gcc [选项] [文件名]选项参数表 参数对应功能-E仅执行编译预处理-S将.c代码转换为汇编语言代码-c仅执行编译操作&#xff0c;不进行连接操作-o指定生成的输出文件-I (大写)指定…

普通计算机怎么算根号_大学专业介绍 | 计算机专业的真实就业情况

前两天给大家简单介绍了近些年比较火的计算机类相关专业具体都有哪些不同&#xff0c;以及就业时的行业或者岗位的侧重点。今天呢我们继续这个话题&#xff0c;来聊一聊整个计算机相关专业在学习和就业过程中大概是什么样子的&#xff0c;希望能够给大家提供一些实实在在的参考…

设计模式总结篇系列:工厂方法模式(Factory Method)

工厂方法模式适合于对实现了同一接口或继承了同一父类的一些类进行实例的创建。一般是通过定义一个工厂类&#xff0c;并在其方法中实现对具有上述特点的类对象的创建。 根据具体产生类对象的方法定义形式&#xff0c;又可以将其分为普通工厂方法模式、多个工厂方法模式和静态工…

高新园区到大连计算机学校,大连高新区中心小学

大连市高新区中心小学简介&#xff1a;大连市高新区中心小学始建于2009年9月&#xff0c;是大连高新技术产业园区筹建的第一所直属公办学校。学校现拥有2000多名学生&#xff0c;87名教职员工。学校确定了“办诗韵教育&#xff0c;让每个孩子都幸福的教育理念”&#xff0c;通过…

java基础之匿名内部类

内部类:   概述: 类里边还有一个类, 里边那个类叫内部类, 外边那个类叫外部类.   分类:  成员内部类: 定义在成员位置的内部类.  局部内部类: 定义在局部位置的内部类. 格式:   new 类名或者接口名(){     //重写类或者接口中 所有的 抽象方法;   };本质:  就…

0限流电阻 stm32_上/下拉电阻

除了前一节讨论的拉电阻基本使用方法外&#xff0c;上拉电阻也可以提升高电平的电压阈值&#xff0c;以便于前后级信号相匹配&#xff0c;比如&#xff0c;TTL逻辑电平驱动CMOS逻辑电平时&#xff0c;我们通常会添加一个上拉电阻R1&#xff0c;如下图所示&#xff1a;But Why&a…

天地与我并存/万物与我为一 2

http://blog.sina.com.cn/s/blog_17e792e010102y4lu.html 庖丁解牛 先秦&#xff1a;庄周 吾生也有涯&#xff0c;而知也无涯 。以有涯随无涯&#xff0c;殆已&#xff01;已而为知者&#xff0c;殆而已矣&#xff01;为善无近名&#xff0c;为恶无近刑。缘督以为经&#xff0c…