Kaka's Matrix Travels
Description On an N × N chessboard with a non-negative number in each grid, Kaka starts his matrix travels with SUM = 0. For each travel, Kaka moves one rook from the left-upper grid to the right-bottom one, taking care that the rook moves only to the right or down. Kaka adds the number to SUM in each grid the rook visited, and replaces it with zero. It is not difficult to know the maximum SUM Kaka can obtain for his first travel. Now Kaka is wondering what is the maximum SUM he can obtain after his Kth travel. Note the SUM is accumulative during the K travels. Input The first line contains two integers N and K (1 ≤ N ≤ 50, 0 ≤ K ≤ 10) described above. The following N lines represents the matrix. You can assume the numbers in the matrix are no more than 1000. Output The maximum SUM Kaka can obtain after his Kth travel. Sample Input 3 2 1 2 3 0 2 1 1 4 2 Sample Output 15 Source POJ Monthly--2007.10.06, Huang, Jinsong
|
[Submit] [Go Back] [Status] [Discuss]
有一个NxN的棋盘,每个格子有一个非负整数。从左上角走到右下角,获得路径格子上的权值(只能向右或向下走),且每个格子的权值只能获得一次,可以理解为经过的格子权值置为0。可以走K次,求获得的最大权值和。
拆点跑最大费用最大流。
每个格子拆成入点和出点,入点向出点连一条容量为1,权值为格子权值的边,表示权值只能获得一次,再连一条容量无穷,权值为0的的边,表示之后可以经过但不获得权值。再按照右下的转移规则连接格子即可。做从左上格子到右下格子,最大流为K的最大费用流即可。
1 #include <cstdio> 2 #include <cstring> 3 4 #define fread_siz 1024 5 6 inline int get_c(void) 7 { 8 static char buf[fread_siz]; 9 static char *head = buf + fread_siz; 10 static char *tail = buf + fread_siz; 11 12 if (head == tail) 13 fread(head = buf, 1, fread_siz, stdin); 14 15 return *head++; 16 } 17 18 inline int get_i(void) 19 { 20 register int ret = 0; 21 register int neg = false; 22 register int bit = get_c(); 23 24 for (; bit < 48; bit = get_c()) 25 if (bit == '-')neg ^= true; 26 27 for (; bit > 47; bit = get_c()) 28 ret = ret * 10 + bit - 48; 29 30 return neg ? -ret : ret; 31 } 32 33 inline int min(int a, int b) 34 { 35 return a < b ? a : b; 36 } 37 38 const int inf = 2e9; 39 40 const int N = 55; 41 const int M = 500005; 42 43 int n, m; 44 int s, t; 45 int edges; 46 int hd[M]; 47 int nt[M]; 48 int to[M]; 49 int fl[M]; 50 int vl[M]; 51 52 int dis[M]; 53 int pre[M]; 54 55 inline bool bfs(void) 56 { 57 static int que[M]; 58 static int inq[M]; 59 static int head, tail; 60 61 memset(dis, -1, sizeof(dis)); 62 memset(inq, 0, sizeof(inq)); 63 head = 0, tail = 0; 64 que[tail++] = s; 65 pre[s] = -1; 66 dis[s] = 0; 67 inq[s] = 1; 68 69 while (head != tail) 70 { 71 int u = que[head++], v; inq[u] = 0; 72 for (int i = hd[u]; ~i; i = nt[i]) 73 if (dis[v = to[i]] < dis[u] + vl[i] && fl[i]) 74 { 75 pre[v] = i ^ 1; 76 dis[v] = dis[u] + vl[i]; 77 if (!inq[v])inq[que[tail++] = v] = 1; 78 } 79 } 80 81 return dis[t] != -1; 82 } 83 84 inline int minCost(void) 85 { 86 int cost = 0; 87 88 while (bfs()) 89 { 90 int flow = inf; 91 92 for (int i = pre[t]; ~i; i = pre[to[i]]) 93 flow = min(flow, fl[i ^ 1]); 94 95 for (int i = pre[t]; ~i; i = pre[to[i]]) 96 fl[i] += flow, fl[i ^ 1] -= flow; 97 98 cost += dis[t] * flow; 99 } 100 101 return cost; 102 } 103 104 inline void add(int u, int v, int f, int w) 105 { 106 nt[edges] = hd[u]; to[edges] = v; fl[edges] = f; vl[edges] = +w; hd[u] = edges++; 107 nt[edges] = hd[v]; to[edges] = u; fl[edges] = 0; vl[edges] = -w; hd[v] = edges++; 108 } 109 110 int G[N][N]; 111 112 inline int h(int x, int y, int k) 113 { 114 return ((x - 1) * n + y) << 1 | k; 115 } 116 117 signed main(void) 118 { 119 n = get_i(); 120 m = get_i(); 121 122 for (int i = 1; i <= n; ++i) 123 for (int j = 1; j <= n; ++j) 124 G[i][j] = get_i(); 125 126 memset(hd, -1, sizeof(hd)); 127 128 s = 0, t = (n*n + 1) << 1 | 1; 129 130 for (int i = 1; i <= n; ++i) 131 for (int j = 1; j <= n; ++j) 132 add(h(i, j, 0), h(i, j, 1), m, 0), 133 add(h(i, j, 0), h(i, j, 1), 1, G[i][j]); 134 135 for (int i = 1; i < n; ++i) 136 for (int j = 1; j <= n; ++j) 137 add(h(i, j, 1), h(i + 1, j, 0), m, 0); 138 139 for (int i = 1; i <= n; ++i) 140 for (int j = 1; j < n; ++j) 141 add(h(i, j, 1), h(i, j + 1, 0), m, 0); 142 143 add(s, h(1, 1, 0), m, 0); 144 add(h(n, n, 1), t, m, 0); 145 146 printf("%d ", minCost()); 147 }
@Author: YouSiki