Acdream 1128 maze (billing flow)

Source: Internet
Author: User

Question link: http://acdream.info/problem? PID = 1, 1128

Problem descriptionwuyiqi falls into a maze consisting of n * m grids. A certain number of boxes are stacked on each grid. (I, j) indicates the grid of row I and column J. Wuyiqi can move a box on a grid to an adjacent grid or destroy it. That is, the boxes in (I, j) can be moved to (I-1, J), (I + 1, J), (I, J-1) and (I, j + 1 ), but cannot be moved out of the matrix range. Moving a box on the (I, j) grid to an adjacent grid consumes the RP value of X and destroying the RP value of Y. When the number of boxes in each row is equal and the number of boxes in each column is equal, wuyiqi can escape. Help wuyiqi calculate the minimum Rp value required for escape. Input

There are multiple groups of data.

The first row of each data group is two positive integers n and M (1 <= n, m <= 100 ).

The following two integers are X and Y (1 <= X, Y <= 100)

In the next n rows, each row has m non-negative integers. The number of J in row I is P (I, j) (0 <= P (I, j) <= 20) it indicates the number of boxes on the (I, j) grid. Output

Output The minimum Rp value required for wuyiqi escape.

 

Question: omitted.

Idea: Considering the results, the sum of each row is the same, and the sum of each column is the same. The sum of each row is a multiple of N, and the sum of each column is a multiple of M. Then the sum of the entire board must be a multiple of LCM (n, m.

Then enumerate the number of remaining boxes in the final board, and enumerate the multiples of LCM (n, m). If it is B, the number of boxes to be destroyed is (Sum-B) * y, sum indicates the total number of boxes.

Now we want to move the boxes between each row and set sumr [I] to the total number of boxes in row I. Now we need to change each row to B/n.

Create a Source Vertex, and the capacity of connecting one edge to each row is sumr [I], and the cost is 0. Create a sink, and each row is connected to one edge of the sink. The capacity is B/N and the cost is 0.

An edge is connected between adjacent rows. The capacity is positive infinity and the fee is X.

The minimum cost of running the largest stream can get the cost of moving the box between rows. Similarly, we can get the cost of moving boxes between columns.

Take the minimum value of the total price after enumeration.

PS: The spfa billing template that has been used in the past is incorrect when debugging is performed with the naked eye ......

 

Code (96 ms ):

  1 #include <cstdio>  2 #include <iostream>  3 #include <algorithm>  4 #include <cstring>  5 #include <queue>  6 #include <numeric>  7 using namespace std;  8 typedef long long LL;  9  10 const int MAXN = 110; 11 const int MAXV = 110; 12 const int MAXE = 8 * MAXV; 13 const int INF = 0x7f7f7f7f; 14  15 struct SPFA_COST_FLOW { 16     int head[MAXV]; 17     int to[MAXE], next[MAXE], cost[MAXE], flow[MAXE]; 18     int n, ecnt, st, ed; 19  20     void init(int nn) { 21         n = nn; 22         memset(head + 1, -1, n * sizeof(int)); 23         ecnt = 0; 24     } 25  26     void add_edge(int u, int v, int c, int w) { 27         to[ecnt] = v; flow[ecnt] = c; cost[ecnt] = w; next[ecnt] = head[u]; head[u] = ecnt++; 28         to[ecnt] = u; flow[ecnt] = 0; cost[ecnt] = -w; next[ecnt] = head[v]; head[v] = ecnt++; 29     } 30  31     bool vis[MAXV]; 32     int dis[MAXV], pre[MAXV]; 33     queue<int> que; 34  35     bool spfa() { 36         memset(vis + 1, 0, n * sizeof(bool)); 37         memset(dis + 1, 0x7f, n * sizeof(int)); 38         dis[st] = 0; que.push(st); 39         while(!que.empty()) { 40             int u = que.front(); que.pop(); 41             vis[u] = false; 42             for(int p = head[u]; ~p; p = next[p]) { 43                 int &v = to[p]; 44                 if(flow[p] && dis[v] > dis[u] + cost[p]) { 45                     dis[v] = dis[u] + cost[p]; 46                     pre[v] = p; 47                     if(!vis[v]) { 48                         que.push(v); 49                         vis[v] = true; 50                     } 51                 } 52             } 53         } 54         return dis[ed] < INF; 55     } 56  57     int maxFlow, minCost; 58     int min_cost_flow(int ss, int tt) { 59         st = ss, ed = tt; 60         maxFlow = minCost = 0; 61         while(spfa()) { 62             int u = ed, tmp = INF; 63             while(u != st) { 64                 tmp = min(tmp, flow[pre[u]]); 65                 u = to[pre[u] ^ 1]; 66             } 67             u = ed; 68             while(u != st) { 69                 flow[pre[u]] -= tmp; 70                 flow[pre[u] ^ 1] += tmp; 71                 u = to[pre[u] ^ 1]; 72             } 73             maxFlow += tmp; 74             minCost += tmp * dis[ed]; 75         } 76         return minCost; 77     } 78 } G; 79  80 int mat[MAXN][MAXN]; 81 int sumr[MAXN], sumc[MAXN]; 82 int n, m, x, y; 83  84 int calc(int sum[], int n, int c) { 85     int ss = n + 1, tt = n + 2; 86     G.init(n + 2); 87     for(int i = 1; i <= n; ++i) 88         G.add_edge(ss, i, sum[i], 0), G.add_edge(i, tt, c, 0); 89     for(int i = 1; i < n; ++i) 90         G.add_edge(i, i + 1, INF, x), G.add_edge(i + 1, i, INF, x); 91     return G.min_cost_flow(ss, tt); 92 } 93  94 int solve() { 95     int sum = accumulate(sumr + 1, sumr + n + 1, 0), ans = sum * y; 96     int lcm = n * m / __gcd(n, m); 97     for(int b = lcm; b <= sum; b += lcm) { 98         ans = min(ans, (sum - b) * y + calc(sumr, n, b / n) + calc(sumc, m, b / m)); 99     }100     return ans;101 }102 103 int main() {104     while(scanf("%d%d", &n, &m) != EOF) {105         scanf("%d%d", &x, &y);106         for(int i = 1; i <= n; ++i)107             for(int j = 1; j <= m; ++j) scanf("%d", &mat[i][j]);108         memset(sumr + 1, 0, n * sizeof(int));109         memset(sumc + 1, 0, m * sizeof(int));110         for(int i = 1; i <= n; ++i) {111             for(int j = 1; j <= m; ++j) {112                 sumr[i] += mat[i][j];113                 sumc[j] += mat[i][j];114             }115         }116         printf("%d\n", solve());117     }118 }
View code

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.