• bzoj2756: [SCOI2012]奇怪的游戏


    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 

     
    题解:
    http://hzwer.com/5992.html
    code:
     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #define maxn 2000
     7 #define maxm 20000
     8 #define inf (1LL<<50)
     9 using namespace std;
    10 typedef long long int64;
    11 char ch;
    12 bool ok;
    13 void read(int &x){
    14     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
    15     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    16     if (ok) x=-x;
    17 }
    18 void read(int64 &x){
    19     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
    20     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    21     if (ok) x=-x;
    22 }
    23 int T,n,m,sta[42][42];
    24 int64 l,r,mid,num0,num1,sum0,sum1,val[42][42];
    25 struct flow{
    26     int s,t,tot,now[maxn],son[maxm],pre[maxm];
    27     int64 val[maxm];
    28     int dis[maxn],head,tail,list[maxn];
    29     bool bo[maxn];
    30     void init(){s=0,t=n*m+1,tot=1,memset(now,0,sizeof(now));}
    31     void put(int a,int b,int64 c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;}
    32     void add(int a,int b,int64 c){put(a,b,c),put(b,a,0);}
    33     bool bfs(){
    34         memset(bo,0,sizeof(bo));
    35         head=0,tail=1,list[1]=s,dis[s]=0,bo[s]=1;
    36         while (head<tail){
    37             int u=list[++head];
    38             for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
    39                 if (val[p]&&!bo[v]) bo[v]=1,dis[v]=dis[u]+1,list[++tail]=v;
    40         }
    41         return bo[t];
    42     }
    43     int64 dfs(int u,int64 rest){
    44         if (u==t) return rest;
    45         int64 ans=0;
    46         for (int p=now[u],v=son[p];p&&rest;p=pre[p],v=son[p])
    47             if (val[p]&&dis[v]==dis[u]+1){
    48                 int64 d=dfs(v,min(rest,val[p]));
    49                 val[p]-=d,val[p^1]+=d,ans+=d,rest-=d;
    50             }
    51         if (!ans) dis[u]=-1;
    52         return ans;
    53     }
    54     int64 dinic(){
    55         int64 ans=0;
    56         while (bfs()) ans+=dfs(s,inf);
    57         return ans;
    58     }
    59 }f,tmp;
    60 bool check(int64 lim){
    61     f=tmp;
    62     int64 tot=0;
    63     for (int i=1;i<=n;i++) for (int j=1;j<=m;j++)
    64         if (sta[i][j]) tot+=lim-val[i][j],f.add(f.s,(i-1)*m+j,lim-val[i][j]);
    65         else f.add((i-1)*m+j,f.t,lim-val[i][j]);
    66     return f.dinic()==tot;
    67 }
    68 const int dx[4]={1,0,-1,0};
    69 const int dy[4]={0,1,0,-1};
    70 int main(){
    71     for (int i=1;i<=40;i++) for (int j=1;j<=40;j++) sta[i][j]=(i+j)&1;
    72     for (read(T);T;T--){
    73         read(n),read(m),l=num0=num1=sum0=sum1=0;
    74         for (int i=1;i<=n;i++) for (int j=1;j<=m;j++){
    75             read(val[i][j]),l=max(l,val[i][j]);
    76             if (sta[i][j]) num0++,sum0+=val[i][j];
    77             else num1++,sum1+=val[i][j];
    78         }
    79         f.init();
    80         for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (sta[i][j])
    81             for (int k=0;k<4;k++){
    82                 int x=i+dx[k],y=j+dy[k];
    83                 if (x<=0||x>n||y<=0||y>m) continue;
    84                 f.add((i-1)*m+j,(x-1)*m+y,inf);
    85             }
    86         tmp=f;
    87         if (num0==num1){
    88             if (sum0!=sum1){puts("-1");continue;}
    89             for (r=inf,mid=(l+r)>>1;l<r;mid=(l+r)>>1) if (check(mid)) r=mid; else l=mid+1;
    90             printf("%lld
    ",l*num0-sum0);
    91         }
    92         else{
    93             int64 ans=(sum0-sum1)/(num0-num1);
    94             if (ans>=l&&check(ans)) printf("%lld
    ",ans*num0-sum0);
    95             else puts("-1");
    96         }
    97     }
    98     return 0;
    99 }
  • 相关阅读:
    WinForm笔记1:TextBox编辑时和DataGridView 单元格编辑时 的事件及其顺序
    Emgu 学习(4) 使用指针访问图像内存
    SolidWorks学习笔记1
    Emgu 学习(3) 绘图,使用鼠标绘图,使用trackbar
    NModbus4的使用
    C# async await的使用
    Emgu 学习(2) 视频文件播放
    redis-key2
    redis--key1
    rpc优化
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/5138741.html
Copyright © 2020-2023  润新知