方格取数问题 最小割

末蓝、 2021-12-16 20:04 419阅读 0赞

题目背景

none!

题目描述

在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。对于给定的方格棋盘,按照取数要求编程找出总和最大的数。

输入输出格式

输入格式:

第 1 行有 2 个正整数 m 和 n,分别表示棋盘的行数和列数。接下来的 m 行,每行有 n 个正整数,表示棋盘方格中的数。

输出格式:

程序运行结束时,将取数的最大总和输出

输入输出样例

输入样例#1: 复制

  1. 3 3
  2. 1 2 3
  3. 3 2 3
  4. 2 3 1

输出样例#1: 复制

  1. 11

说明

m,n<=100

总和sum- dinic();

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<string>
  7. #include<cmath>
  8. #include<map>
  9. #include<set>
  10. #include<vector>
  11. #include<queue>
  12. #include<bitset>
  13. #include<ctime>
  14. #include<deque>
  15. #include<stack>
  16. #include<functional>
  17. #include<sstream>
  18. //#include<cctype>
  19. //#pragma GCC optimize(2)
  20. using namespace std;
  21. #define maxn 100005
  22. #define inf 0x7fffffff
  23. //#define INF 1e18
  24. #define rdint(x) scanf("%d",&x)
  25. #define rdllt(x) scanf("%lld",&x)
  26. #define rdult(x) scanf("%lu",&x)
  27. #define rdlf(x) scanf("%lf",&x)
  28. #define rdstr(x) scanf("%s",x)
  29. typedef long long ll;
  30. typedef unsigned long long ull;
  31. typedef unsigned int U;
  32. #define ms(x) memset((x),0,sizeof(x))
  33. const long long int mod = 1e9;
  34. #define Mod 1000000000
  35. #define sq(x) (x)*(x)
  36. #define eps 1e-5
  37. typedef pair<int, int> pii;
  38. #define pi acos(-1.0)
  39. //const int N = 1005;
  40. #define REP(i,n) for(int i=0;i<(n);i++)
  41. typedef pair<int, int> pii;
  42. inline int rd() {
  43. int x = 0;
  44. char c = getchar();
  45. bool f = false;
  46. while (!isdigit(c)) {
  47. if (c == '-') f = true;
  48. c = getchar();
  49. }
  50. while (isdigit(c)) {
  51. x = (x << 1) + (x << 3) + (c ^ 48);
  52. c = getchar();
  53. }
  54. return f ? -x : x;
  55. }
  56. ll gcd(ll a, ll b) {
  57. return b == 0 ? a : gcd(b, a%b);
  58. }
  59. int sqr(int x) { return x * x; }
  60. /*ll ans;
  61. ll exgcd(ll a, ll b, ll &x, ll &y) {
  62. if (!b) {
  63. x = 1; y = 0; return a;
  64. }
  65. ans = exgcd(b, a%b, x, y);
  66. ll t = x; x = y; y = t - a / b * y;
  67. return ans;
  68. }
  69. */
  70. int n, m;
  71. int st, ed;
  72. struct node {
  73. int u, v, nxt, w;
  74. }edge[maxn << 1];
  75. int head[maxn], cnt;
  76. void addedge(int u, int v, int w) {
  77. edge[cnt].u = u; edge[cnt].v = v; edge[cnt].nxt = head[u];
  78. edge[cnt].w = w; head[u] = cnt++;
  79. }
  80. int rk[maxn];
  81. int bfs() {
  82. queue<int>q;
  83. ms(rk);
  84. rk[st] = 1;
  85. q.push(st);
  86. while (!q.empty()) {
  87. int tmp = q.front(); q.pop();
  88. for (int i = head[tmp]; i != -1; i = edge[i].nxt) {
  89. int to = edge[i].v;
  90. if (rk[to] || edge[i].w <= 0)continue;
  91. rk[to] = rk[tmp] + 1; q.push(to);
  92. }
  93. }
  94. return rk[ed];
  95. }
  96. int dfs(int u, int flow) {
  97. if (u == ed)return flow;
  98. int add = 0;
  99. for (int i = head[u]; i != -1 && add < flow; i = edge[i].nxt) {
  100. int v = edge[i].v;
  101. if (rk[v] != rk[u] + 1 || !edge[i].w)continue;
  102. int tmpadd = dfs(v, min(edge[i].w, flow - add));
  103. if (!tmpadd) { rk[v] = -1; continue; }
  104. edge[i].w -= tmpadd; edge[i ^ 1].w += tmpadd;
  105. add += tmpadd;
  106. }
  107. return add;
  108. }
  109. int ans;
  110. void dinic() {
  111. while (bfs())ans += dfs(st, inf);
  112. }
  113. //int n, m;
  114. int a[200][200];
  115. int dx[] = { 0,0,-1,1 };
  116. int dy[] = { 1,-1,0,0 };
  117. bool OK(int x, int y) {
  118. return x >= 1 && x <= n && y >= 1 && y <= m;
  119. }
  120. int getpos(int x, int y) {
  121. return (x - 1)*m + y;
  122. }
  123. int main()
  124. {
  125. // ios::sync_with_stdio(0);
  126. n = rd(); m = rd(); memset(head, -1, sizeof(head));
  127. int sum = 0;
  128. for (int i = 1; i <= n; i++) {
  129. for (int j = 1; j <= m; j++)a[i][j] = rd(), sum += a[i][j];
  130. }
  131. st = 0; ed = n * m + 4;
  132. for (int i = 1; i <= n; i++) {
  133. for (int j = 1; j <= m; j++) {
  134. if ((i + j) % 2)addedge(st, getpos(i, j), a[i][j]), addedge(getpos(i, j), st, a[i][j]);
  135. else addedge(getpos(i, j), ed, a[i][j]), addedge(ed, getpos(i, j), 0);
  136. }
  137. }
  138. for (int i = 1; i <= n; i++) {
  139. for (int j = 1; j <= m; j++) {
  140. if ((i + j) % 2) {
  141. for (int k = 0; k < 4; k++) {
  142. int nx = i + dx[k];
  143. int ny = j + dy[k];
  144. if (OK(nx, ny))addedge(getpos(i, j), getpos(nx, ny), inf), addedge(getpos(nx, ny), getpos(i, j), 0);
  145. }
  146. }
  147. }
  148. }
  149. //cout << 1 << endl;
  150. dinic();
  151. printf("%d\n", sum - ans);
  152. return 0;
  153. }

转载于:https://www.cnblogs.com/zxyqzy/p/10353555.html

发表评论

表情:
评论列表 (有 0 条评论,419人围观)

还没有评论,来说两句吧...

相关阅读

    相关 [NOIP2000]方格

    题目描述 设有\\(N×N\\)的方格图\\((N≤9)\\),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0。如下图所示(见样例): A 0 0 0

    相关 网络流-

    最大流最小割定理:最大流最小割定理是[网络流][Link 1]理论的重要定理。是指在一个网络流中,能够从源点到达汇点的最大流量等于如果从网络中移除就能够导致网络流中断的边的集合

    相关 方格

    题目描述 设有N \\times NN×N的方格图(N \\le 9)(N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字00。如下图所示(见样例):

    相关 方格问题

    题目背景 none! 题目描述 在一个有 m\n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最