zoukankan      html  css  js  c++  java
  • 【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 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
     

     

    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边,看是否满流。

     

      1 /*2
      2 2 2
      3 1 2
      4 2 3
      5 3 3
      6 1 2 3
      7 2 3 4
      8 4 3 2
      9 没去freopen居然调了半个小时,醉了。
     10 inf和INF什么的,最讨厌了。
     11 染色技巧很玄妙! 
     12 */
     13 #include <cstdio>
     14 #include <iostream>
     15 #include <cstring>
     16 #include <algorithm>
     17 #include <queue>
     18 #include <vector>
     19 #include <ctime>
     20 #include <cmath>
     21 #define ll long long
     22 #define N 50
     23 #define mem(f,a) memset(f,a,sizeof(f))
     24 #define Run(i,l,r) for(ll i=l;i<=r;i++)
     25 #define Don(i,l,r) for(ll i=l;i>=r;i--)
     26 #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)
     27 using namespace std;
     28 int n,m;
     29 const ll inf=(1LL<<49);
     30 const ll INF=(1LL<<60);
     31 struct Edge{
     32     int v,next;
     33     ll cap,flow;
     34 }E[1000000];
     35 ll a[N][N],color[N][N];
     36 ll head[N*N],k,cur[N*N],vis[N*N],d[N*N];
     37 int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
     38 queue<int>q;
     39 int idx(int i,int j){return (i-1)*m+j;}
     40 void adde(int u,int v,ll cap)
     41 {    E[k]=(Edge){v,head[u],cap,0};
     42     head[u]=k++;
     43     E[k]=(Edge){u,head[v],0,0};
     44     head[v]=k++;
     45 }
     46 bool Bfs()
     47 {    mem(vis,0); mem(d,0);
     48     vis[0]=1; q.push(0);
     49     while (!q.empty()){
     50         int u=q.front(); q.pop();
     51         Eun(i,u,E,head)if (E[i].cap>E[i].flow&&!vis[v]){
     52             vis[v]=1;
     53             q.push(v);
     54             d[v]=d[u]+1;
     55         }
     56     }
     57     return (vis[n*m+1]);
     58 }
     59 ll Dfs(int u,ll a)
     60 {    if (u==n*m+1||a==0) return a;
     61     ll flow=0,f;
     62     Eun(i,u,E,cur){
     63         cur[u]=i;
     64         if (d[v]==d[u]+1&&(f=Dfs(v,min(E[i].cap-E[i].flow,a)))>0){
     65             flow+=f;
     66             a-=f;
     67             E[i].flow+=f;
     68             E[i^1].flow-=f;
     69         }
     70         if (a==0) break;
     71     }
     72     return flow;
     73 }
     74 ll Dinic()
     75 {    ll flow=0;
     76     while (Bfs()){
     77         Run(i,0,n*m+1) cur[i]=head[i];
     78         flow+=Dfs(0,INF);
     79     }
     80     return flow;
     81 }
     82 bool check(ll x)
     83 {    k=0; mem(head,-1);
     84     ll tot=0;
     85     Run(i,1,n)
     86     Run(j,1,m){
     87         if (color[i][j]) {
     88             tot+=x-a[i][j];
     89             adde(0,idx(i,j),x-a[i][j]);
     90             Run(k,0,3){
     91                 int ni=i+dx[k]; int nj=j+dy[k];
     92                 if (ni>0&&nj>0&&ni<=n&&nj<=m) adde(idx(i,j),idx(ni,nj),INF);
     93             }
     94         }
     95         else adde(idx(i,j),n*m+1,x-a[i][j]);
     96     }
     97     if (tot==Dinic()) return 1;
     98     else return 0;
     99 }
    100 int main()
    101 {    freopen("game.in","r",stdin);
    102     freopen("game.out","w",stdout);
    103     int T;
    104     scanf("%d",&T);
    105     while (T--){
    106         scanf("%d%d",&n,&m);
    107         ll maxn=0,num1=0,num2=0; ll sum1=0,sum2=0;
    108         Run(i,1,n)
    109         Run(j,1,m){
    110             scanf("%lld",&a[i][j]);
    111             maxn=max(maxn,a[i][j]);
    112             if ((i+j)&1) color[i][j]=1,sum1+=a[i][j],num1++;
    113             else color[i][j]=0,sum2+=a[i][j],num2++;
    114         }
    115         if (num1==num2) {
    116             if (sum1!=sum2) {printf("-1
    "); continue;}
    117             ll l=maxn,r=inf,x=0; 
    118             while (l<r){
    119                 ll mid=(l+r)/2;
    120                 if (check(mid)) x=mid,r=mid;
    121                 else l=mid+1;    
    122             }
    123             if (x) printf("%lld
    ",1ll*x*num1-sum1);
    124             else printf("-1
    ");
    125         }
    126         else {
    127             ll temp=(sum1-sum2)/(num1-num2);
    128             if (temp>=maxn&&check(temp)) printf("%lld
    ",1ll*temp*num1-sum1); 
    129             else printf("-1
    ");
    130         }
    131     }
    132     return 0;
    133 }//by tkys_Austin;
    View Code

     

     

  • 相关阅读:
    小坦克 沪牌代拍 包中 不中赔100
    JMeter 测试 ActiveMq
    上海程序员 落户攻略
    性能测试(一) 基础概念
    2017 沪牌中标后流程
    2017 上海车牌(沪牌)标书购买攻略
    2017年 外牌转沪牌 攻略 (沪南路车管所)
    Android Monkey 压力测试 介绍
    Android ADB 用法
    Python自动化测试 (九)urllib2 发送HTTP Request
  • 原文地址:https://www.cnblogs.com/Damitu/p/8167651.html
Copyright © 2011-2022 走看看