FZU 2143 Board Game

Board Game

Accept: 95    Submit: 246
Time Limit: 1000 mSec    Memory Limit : 32768 KB

 Problem Description

Fat brother and Maze are playing a kind of special (hentai) game on an N*M board (N rows, M columns). At the beginning, each grid of the board which is own by Fat brother is consisting of an integer 0. At each turn, he can choose two adjacent grids and add both the integer inside them by 1. But due to some unknown reason, the number of each grid can not be large than a given integer K. Also, Maze has already drown an N*M board with N*M integers inside each grid. What Fat brother would like to do is adding his board to be as same as Maze’s. Now we define the different value of two boards A and B as:

 

 

Now your task is to help Fat brother the minimal value of S he can get.

 Input

The first line of the date is an integer T, which is the number of the text cases.

Then T cases follow, each case contains three integers N, M and K which are mention above. Then N lines with M integers describe the board.

1 <= T <= 100, 1 <= N, M, K <= 9

0 <= the integers in the given board <= 9

 Output

For each case, output the case number first, then output the minimal value of S Fat brother can get.

 Sample Input

5 2 2 9 3 4 2 3 1 3 9 4 6 4 1 1 9 9 3 3 5 1 2 3 4 5 6 7 8 9 3 3 9 1 2 3 4 5 6 7 8 9

 Sample Output

Case 1: 0 Case 2: 2 Case 3: 81 Case 4: 33 Case 5: 5

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <queue>
  6 using namespace std;
  7 
  8 const int E = 50010;
  9 const int oo = 0x7fffffff;
 10 const int inf = 10000;
 11 const int maxn = 1010;
 12 
 13 struct edge
 14 {
 15     int next,v,flow,cost;
 16 } e[E];
 17 
 18 struct MCMF
 19 {
 20     int head[maxn];
 21     queue<int> q;
 22     int cnt, S, T;
 23     void init(int __S,int __T)
 24     {
 25         S = __S;
 26         T = __T;
 27         memset(head,-1,sizeof(head));
 28         cnt = 0;
 29     }
 30     void add(int u,int v,int flow,int cost)
 31     {
 32         e[cnt].v = v;
 33         e[cnt].flow = flow;
 34         e[cnt].cost = cost;
 35         e[cnt].next = head[u];
 36         head[u] = cnt ++;
 37     }
 38 
 39     void AddEdge(int u,int v,int flow,int cost)
 40     {
 41         add(u,v,flow,cost);
 42         add(v,u,0, -cost);
 43     }
 44 
 45 
 46 
 47     int dis[maxn],cc[maxn],visit[maxn],pre[maxn],dd[maxn];
 48 
 49     int spfa()
 50     {
 51         fill(dis,dis + T + 1, oo);
 52         dis[S] = 0;
 53         pre[S] = -1;
 54         q.push(S);
 55         while(!q.empty())
 56         {
 57             int u = q.front();
 58             q.pop();
 59             visit[u] = 0;
 60             for(int i = head[u]; i != -1; i = e[i].next)
 61             {
 62                 if(e[i].flow > 0 && dis[e[i].v] > dis[u] + e[i].cost)
 63                 {
 64                     dis[e[i].v] = dis[u] + e[i].cost;
 65                     pre[e[i].v] = u;
 66                     cc[e[i].v] = i;
 67                     dd[e[i].v] = e[i].cost;
 68                     if(!visit[e[i].v])
 69                     {
 70                         q.push(e[i].v);
 71                         visit[e[i].v] = 1;
 72                     }
 73                 }
 74             }
 75         }
 76         return dis[T] < 0;
 77     }
 78 
 79     int argument()
 80     {
 81         int aug = oo;
 82         int u,v;
 83         int ans = 0;
 84         for(u = pre[v = T]; v != S; v = u, u = pre[v])
 85             if(e[cc[v]].flow < aug) aug = e[cc[v]].flow;
 86         for(u = pre[v = T]; v != S; v = u, u = pre[v])
 87         {
 88             e[cc[v]].flow -= aug;
 89             e[cc[v] ^ 1].flow += aug;
 90             ans += dd[v] * aug;
 91         }
 92         return ans;
 93     }
 94 
 95     int mcmf()
 96     {
 97         int res = 0;
 98         memset(visit,0,sizeof(visit));
 99         while(spfa()) res += argument();
100         return res;
101     }
102 } MC;
103 
104 
105 int N,M,K;
106 int b[11][11];
107 
108 int main()
109 {
110     int cas, cast = 0;
111     scanf("%d",&cas);
112     while (cas--)
113     {
114         scanf("%d%d%d",&N,&M,&K);
115         for (int i=1;i<=N;i++)
116         {
117             for (int j=1;j<=M;j++)
118             {
119                 scanf("%d",&b[i][j]);
120             }
121         }
122 
123 
124         int nn = N * M + 2, s = 0, t = N*M + 1;
125         MC.init(s,t);
126         int ans = 0;
127         for (int i=1;i<=N;i++)
128         for (int j=1;j<=M;j++)
129         {
130             ans += b[i][j] * b[i][j];
131             int p = i*M - M + j;
132             if ((i+j)%2==0){
133                 for (int k=1;k<=K;k++)
134                 {
135                     int tmp = 2 * k - 1 - 2 * b[i][j];
136                     MC.AddEdge(s,p, 1,tmp);
137                 }
138                 int pp = 0;
139                 if (i<N)
140                 {
141                     pp = p + M;
142                     MC.AddEdge(p,pp,inf,0);
143                 }
144                 if (i>1)
145                 {
146                     pp = p - M;
147                     MC.AddEdge(p,pp,inf,0);
148                 }
149                 if (j<M)
150                 {
151                     pp = p + 1;
152                     MC.AddEdge(p,pp,inf,0);
153                 }
154                 if (j>1)
155                 {
156                     pp = p - 1;
157                     MC.AddEdge(p,pp,inf,0);
158                 }
159             }else{
160                 for (int k=1;k<=K;k++)
161                 {
162                     int tmp = 2 * k - 1 - 2 * b[i][j];
163                     MC.AddEdge(p,t, 1,tmp);
164                 }
165             }
166         }
167       //  MC.AddEdge(s,t,INF,0);
168         printf("Case %d: %d\n",++cast, ans + MC.mcmf());
169     }
170     return 0;
171 }
View Code

 

posted @ 2015-08-30 19:29  cyd2014  阅读(164)  评论(0编辑  收藏  举报