日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

方格取数问题

發布時間:2025/3/12 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 方格取数问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

方格取數問題

有一個m行n列的方格圖,每個方格中都有一個正整數。現要從方格中取數,使任意兩個數所在方格沒有公共邊,且取出的數的總和最大,請求出最大的和。
數據范圍1<=n,m<=100

把這個最小割的題補了

網絡流的題最難的還是在于建模。在這個題目中,首先我們假設所有的數都取出來了,然后放棄一部分數來使其合法。因為相鄰的兩個點不能同時取,所以它們之前的邊容量應該是inf,根據行與列之和的奇偶性,可以將原圖轉化為一個二分圖,源點向其中一邊的點連接容量為a[i][j]的邊,另一邊向匯點連接容量為a[i][j]的邊,最后得到的新圖當中找到最小割就是放棄的邊的集合。用總的減去這個集合,得到的剩余的邊就是選擇的。

最小割求法就是最大流。

又一次忘了在bfs拓展節點的時候忘了flow>0的條件

const int N = 110, M = 1e6, inf = 1e9 + 7; int a[N][N], head[N * N], now[N * N], num = -1, dis[N * N]; int n, m, sum = 0, s, t; bool vis[N * N];struct edge {int nxt, to, flow; }; edge e[M];void addEdge(int x, int y, int z) {e[++ num].nxt = head[x];head[x] = num;e[num].to = y;e[num].flow = z; }inline int getNum(int x, int y) {return (x - 1) * m + y; }bool bfs() {for (int i = 0; i <= n * m + 1; i ++)dis[i] = inf;dis[s] = 0;queue <int> q;q.push(s);while (!q.empty()){int x = q.front(); q.pop();for (int i = head[x]; i != -1; i = e[i].nxt){int to = e[i].to;if (dis[to] > dis[x] + 1 && e[i].flow > 0){dis[to] = dis[x] + 1;q.push(to);}}}if (dis[t] == inf)return false;return true; }int dfs(int x, int flow) {if (vis[x])return 0;vis[x] = 1;if (x == t)return flow;for (int i = now[x]; i != -1; i = e[i].nxt){now[x] = i;int to = e[i].to;if (dis[to] == dis[x] + 1 && e[i].flow){int val = dfs(to, min(flow, e[i].flow));if (val > 0){e[i].flow -= val;e[i ^ 1].flow += val;return val;}}}return 0; }void dinic(int x, int y) {s = x; t = y;while (bfs()){for (int i = 0; i <= n * m + 1; i ++){now[i] = head[i];vis[i] = 0;}int val = 0;while (val = dfs(s, inf)){if (val == 0) break;sum -= val;}} }int main() {//freopen("in.txt", "r", stdin);memset (head, -1, sizeof (head));n = read(); m = read();for (int i = 1; i <= n; i ++)for (int j = 1; j <= m; j ++){a[i][j] = read();sum += a[i][j];}for (int i = 1; i <= n; i ++)for (int j = 1; j <= m; j ++){int temp = getNum(i, j);if ((i + j) % 2 == 0){addEdge(0, temp, a[i][j]);addEdge(temp, 0, 0);if(i > 1){addEdge(temp, temp - m, inf);addEdge(temp - m, temp, 0);}if (i < n){addEdge(temp, temp + m, inf);addEdge(temp + m, temp, 0);}if (j > 1){addEdge(temp, temp - 1, inf);addEdge(temp - 1, temp, 0);}if (j < m){addEdge(temp, temp + 1, inf);addEdge(temp + 1, temp, 0);}}else{addEdge(temp, n * m + 1, a[i][j]);addEdge(n * m + 1, temp, 0);}}dinic(0, n * m + 1);cout << sum;return 0; }

總結

以上是生活随笔為你收集整理的方格取数问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。