刷题总结——奇怪的游戏(scoi2012)
题目:
题目描述
Blinker 最近喜欢上一个奇怪的游戏。
这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数。每次 Blinker 会选择两个相邻的格子,并使这两个数都加上 1。
现在 Blinker 想知道最少多少次能使棋盘上的数都变成同一个数,如果永远不能变成同一个数则输出 -1。
输入格式
输入的第一行是一个整数 T,表示输入数据有T 轮游戏组成。
每轮游戏的第一行有两个整数 N 和 M , 分别代表棋盘的行数和列数。
接下来有 N 行,每行 M 个数。
输出格式
对于每个游戏输出最少能使游戏结束的次数,如果永远不能变成同一个数则输出 -1。
样例数据 1
备注
【数据范围】
对于 30% 的数据,保证 T<=10,1<=N,M<=8
对于 100% 的数据,保证 T<= 10,1<=N,M<=40,所有数为正整数且小于 1000000000
题解:
这里引用http://www.cnblogs.com/DaD3zZ-Beyonder/p/5765882.html:
一道比较有趣的题目
先对题目进行分析:
首先我们考虑对棋盘黑白染色,那么我们发现:“每次相邻两个+1”,显然是一黑一白+1
那么我们先统计出WhiteNum,BlackNum(黑白点的数目),WhiteSum,BlackSum(黑白点初始权值和)(接下来可能用Wn,Ws,Bn,Bs代替)
那么对于一次增加,显然是WhiteSum+1,BlackSum+1
考虑对最后的情况进行讨论:
那么很显然,当WhiteNum==BlackNum时(即总点数为偶数)
如果WhiteSum!=BlackSum,显然无解
如果WhiteSum==BlackSum时,我们发现,对于X如果成立,那么X+1一定成立,显然满足二分的性质,那么二分这个值,进行判定
当WhiteNum!=BlackNum时(即总点数为奇数)
发现显然,若有解,则解唯一,那么直接验证正确性即可
至于解怎么求?
设最后所有数变为X,易得X*Wn-Ws=X*Bn-Bs,整理下可得:X=(Ws-Bs)/(Wn-Bn),用网络流验证即可
那么考虑建图:
S-->白点,约束为X-val[i][j]
黑点-->T,约束为X-val[i][j]
相邻的白点-->黑点,约束为INF
判断是否满流即可
最后说下个人心得:
这道题的重点其实不是网络流,而是黑白染色这一想法,由相邻格子染色其实可以考虑到这一点,以后做到相似的题要注意这一想法····然后就是后面的分类讨论···也是由黑白染色后考虑答案的性质得出的·····这是一道很好的题,染色+二分+网络流;
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N=;
const int M=;
const long long inf=1e+;
int Ri()
{
char c;
int f=;
for(c=getchar();c<''||c>'';c=getchar());
for(;c<=''&&c>='';c=getchar())
f=(f<<)+(f<<)+c-'';
return f;
}
long long Rl()
{
char c;
long long f=;
for(c=getchar();c<''||c>'';c=getchar());
for(;c<=''&&c>='';c=getchar())
f=f*+c-'';
return f;
}
int T,n,m,tot,first[N],cur[N],lev[N],next[M],go[M],Wn,Bn,src,des;
int color[N][N],num[N][N];
long long map[N][N],rest[M],Ws,Bs,ans,sum;
inline void comb(int a,int b,long long c)
{
next[++tot]=first[a],first[a]=tot,go[tot]=b,rest[tot]=c;
next[++tot]=first[b],first[b]=tot,go[tot]=a,rest[tot]=;
}
inline bool bfs()
{
for(int i=src;i<=des;i++) cur[i]=first[i],lev[i]=-;
static int que[N],tail,u,v;
que[tail=]=src;
lev[src]=;
for(int head=;head<=tail;head++)
{
u=que[head];
for(int e=first[u];e;e=next[e])
{
if(lev[v=go[e]]==-&&rest[e])
{
lev[v]=lev[u]+;
que[++tail]=v;
if(v==des) return true;
}
}
}
return false;
}
inline long long dinic(int u,long long flow)
{
if(u==des)
return flow;
long long res=,delta;
int v;
for(int &e=cur[u];e;e=next[e])
{
if(lev[v=go[e]]>lev[u]&&rest[e])
{
delta=dinic(v,min(flow-res,rest[e]));
if(delta)
{
rest[e]-=delta;
rest[e^]+=delta;
res+=delta;
if(res==flow) break;
}
}
}
if(flow!=res) lev[u]=-;
return res;
}
inline long long maxflow()
{
long long temp=;
while(bfs())
temp+=dinic(src,inf);
return temp;
}
inline bool jud(int x,int y)
{
return x>=&&x<=n&&y>=&&y<=m;
}
inline bool check(long long lim)
{
tot=;
memset(first,,sizeof(first));
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
if(
!color[i][j])
comb(src,num[i][j],lim-map[i][j]);
else
comb(num[i][j],des,lim-map[i][j]);
}
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(!color[i][j])
{
if(jud(i-,j))
comb(num[i][j],num[i-][j],inf);
if(jud(i+,j))
comb(num[i][j],num[i+][j],inf);
if(jud(i,j-))
comb(num[i][j],num[i][j-],inf);
if(jud(i,j+))
comb(num[i][j],num[i][j+],inf);
}
long long temp=maxflow();
if(temp==((long long)Wn*lim-Ws))
return true;
else return false;
}
inline void solve()
{
Wn=Ws=Bn=Bs=;
src=;
des=n*m+;
int cnt=;
long long left=,right=1e+;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
num[i][j]=++cnt;
color[i][j]=(i+j)%;
if(!color[i][j])
Wn++,Ws+=map[i][j];
else
Bn++,Bs+=map[i][j];
left=max(left,map[i][j]);
}
if(Wn==Bn)
{
if(Ws!=Bs)
{
cout<<"-1"<<endl;
return;
}
else
{
while(left<=right)
{
long long mid=(left+right)/;
if(check(mid)) ans=mid,right=mid-;
else left=mid+;
}
cout<<ans*Wn-Ws<<endl;
}
}
else
{
ans=(long long)(Ws-Bs)/(Wn-Bn);
if(ans<left)
{
cout<<"-1"<<endl;
return;
} if(check(ans))
{
cout<<ans*Wn-Ws<<endl;
return;
}
else cout<<"-1"<<endl;
}
}
int main()
{
// freopen("a.in","r",stdin);
T=Ri();
while(T--)
{
n=Ri(),m=Ri();
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
map[i][j]=Rl();
solve();
}
return ;
}
刷题总结——奇怪的游戏(scoi2012)的更多相关文章
- C#LeetCode刷题之#55-跳跃游戏(Jump Game)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3674 访问. 给定一个非负整数数组,你最初位于数组的第一个位置. ...
- C#LeetCode刷题-数组
数组篇 # 题名 刷题 通过率 难度 1 两数之和 C#LeetCode刷题之#1-两数之和(Two Sum) 43.1% 简单 4 两个排序数组的中位数 C#LeetCode刷题之#4-两个排序数组 ...
- 【BZOJ】【2756】【SCOI2012】奇怪的游戏
网络流-最大流 这题……建模部分先略过 这道题是会卡时限的T_T俺的Dinic被卡了,在此放几篇很棒的讲网络流算法的文章,至于大家耳熟能详的论文就不放了…… http://www.cppblog.co ...
- [题目] Luogu P5038 [SCOI2012]奇怪的游戏
学习资料 -----1----- -----2----- P5038 [SCOI2012]奇怪的游戏 一道甚神但没用到高深模型的题 思路 没思路,看题解吧 代码 #include <iostre ...
- BZOJ 2756: [SCOI2012]奇怪的游戏 [最大流 二分]
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 3352 Solved: 919[Submit][Stat ...
- Bzoj2756 [SCOI2012]奇怪的游戏
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 3220 Solved: 886 Description ...
- 一次失败的刷题经历:[LeetCode]292之尼姆游戏(Nim Game)(转)
最近闲来无事刷LeetCode,发现这道题的Accept Rate还是挺高的,尝试着做了一下,结果悲剧了,把过程写下来,希望能长点记性.该题的描述翻译成中文如下: 你正在和你的朋友玩尼姆游戏(Nim ...
- bzoj 2756: [SCOI2012]奇怪的游戏
Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻 的格子,并使这两个数都加上 1. 现在 B ...
- BZOJ 2756: [SCOI2012]奇怪的游戏 网络流/二分
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 1594 Solved: 396[Submit][Stat ...
随机推荐
- path与classpath区别(转)
转自http://blog.csdn.net/mydreamongo/article/details/8155408 1.path的作用 path是系统用来指定可执行文件的完整路径,即使不在path中 ...
- 解决 FusionCharts3.2.1 首页无法载入的问题
在实际项目中测试FusionCharts3.2.1时,发现首次载入无法正常载入,第二次载入就恢复正常! 原因:FusionCharts ID与变量名重复 以下是正常写法: var member ...
- Vue v-if与v-show的区别
用了 viewjs 预览图片的时候 发现 用着两个 还是有区别的, 相同点==== v-if与v-show都可以动态控制dom元素显示隐藏 不同点 = ====v-if显示隐藏是将dom元素整个添加 ...
- CSS3与弹性盒布局
1.弹性盒布局对齐模式 1.1.弹性盒子 在规定弹性盒子之中的子级元素换行显示之前父级元素必须是弹性盒子模型,也就是设置 display 为 flex 代码如下: <!DOCTYPE html& ...
- Mac app 破解之路
6年之前一直做过一些内存挂,脚本挂.都是比较低级的技术. 这几年期间,断断续续利用业余时间学了一些汇编的知识,当时只是想着破解游戏. 所有的黑技术都是业余自学的,没有老师可以问,只能百度和自己领悟,比 ...
- 新数据的GT列表
制作新数据集时需要重新制作train_GT,test_GT 代码: dic = {} with open('/home/bnrc/all_image_GT.txt','r') as file: for ...
- Jordan 标准型的实例
将学习到什么 练习一下如何把一个矩阵化为 Jordan 标准型. 将矩阵化为 Jordan 标准型需要三步: 第一步 求出矩阵 \(A \in M_n\) 全部的特征值 \(\lambda_1,\ ...
- 在行列都排好序的矩阵中找数 【题目】 给定一个有N*M的整型矩阵matrix和一个整数K, matrix的每一行和每一 列都是排好序的。实现一个函数,判断K 是否在matrix中。 例如: 0 1 2 5 2 3 4 7 4 4 4 8 5 7 7 9 如果K为7,返回true;如果K为6,返 回false。 【要求】 时间复杂度为O(N+M),额外空间复杂度为O(1)。
从对角考虑 package my_basic.class_3; /** * 从对角开始 */ public class Code_09_FindNumInSortedMatrix { public s ...
- ios 之CGRectMake
首先要弄懂几个基本的概念. 一)三个结构体:CGPoint.CGSize.CGRect 1. CGPoint [plain] view plaincopy /* Points. */ struc ...
- 【数学 裴蜀定理】bzoj2257: [Jsoi2009]瓶子和燃料
使gcd最大的trick Description jyy就一直想着尽快回地球,可惜他飞船的燃料不够了. 有一天他又去向火星人要燃料,这次火星人答应了,要jyy用飞船上的瓶子来换.jyy的飞船上共有 N ...