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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

[CQOI2012]交换棋子【网络流】【费用流】

發布時間:2024/6/21 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [CQOI2012]交换棋子【网络流】【费用流】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目描述

有一個nm列的黑白棋盤,你每次可以交換兩個相鄰格子(相鄰是指有公共邊或公共頂點)中的棋子,最終達到目標狀態。要求第i行第j列的格子只能參與mi,j次交換。

輸入輸出格式

輸入格式:

第一行包含兩個整數nm(1n,m20)。以下n行為初始狀態,每行為一個包含m個字符的01串,其中0表示黑色棋子,1表示白色棋子。以下n行為目標狀態,格式同初始狀態。以下n行每行為一個包含m0..9數字的字符串,表示每個格子參與交換的次數上限。

輸出格式:

輸出僅一行,為最小交換總次數。如果無解,輸出?1

解法:

一眼費用流系列…然而這題的處理有點詭異,首先要拆點將點的限制轉化為邊的限制,SINi,OUTiTINOUT的權值是多少?分三種情況討論:

  • 既不是起始也不是結束狀態:?n2?
  • 既是起始也是結束狀態:?n+22?
  • 是起始或結束狀態:?n+12?
  • #include <bits/stdc++.h> using namespace std;const int MAXN = 2005; struct node {int to, next, f, c, neg; } edge[MAXN*40]; int head[MAXN], top = 0; void push(int i, int j, int k, int l) {if (i*j == 0) return;++top, edge[top] = (node) {j, head[i], k, l, top+1}, head[i] = top;++top, edge[top] = (node) {i, head[j], 0, -l, top-1}, head[j] = top; }int vis[MAXN], dis[MAXN], S = 2001, T = 2002; queue<int> que; int pre[MAXN], pre_edge[MAXN]; const int INF = 233333333;bool spfa() {memset(dis, 127/3, sizeof dis);memset(pre, 0, sizeof pre);vis[S] = 1, que.push(S), dis[S] = 0;while (!que.empty()) {int tp = que.front(); que.pop(), vis[tp] = 0;for (int i = head[tp]; i; i = edge[i].next) {if (edge[i].f == 0 || dis[edge[i].to] <= dis[tp] + edge[i].c) continue;int to = edge[i].to, c = edge[i].c;dis[to] = dis[tp] + c, pre[to] = tp, pre_edge[to] = i;if (!vis[to])vis[to] = 1, que.push(to);}}return dis[T] < INF; }int sap(int &cost) {int ans = INF;for (int i = T; i != S; i = pre[i]) ans = min(ans, edge[pre_edge[i]].f);for (int i = T; i != S; i = pre[i]) edge[pre_edge[i]].f -= ans, edge[edge[pre_edge[i]].neg].f += ans;cost += ans*dis[T];return ans; }int mst(int &cost) {cost = 0;int ans = 0;while (spfa()) ans += sap(cost);return ans; }int n, m; int A[30][30], B[30][30], C[30][30]; char str[30];int readln(int A[30][30]) {int cnt = 0;for (int i = 1; i <= n; i++) {scanf("%s", str+1);for (int j = 1; j <= m; j++)A[i][j] = str[j]-'0', cnt += A[i][j];}return cnt; }inline int number(int i, int j, int id) { return (i<=0||i>n||j<=0||j>m)?0:id*n*m+(i-1)*m+j; }int dx[] = {1,0,-1,0, 1, 1, -1, -1}, dy[] = {0,1,0,-1, -1, 1, -1, 1}; int main() {scanf("%d%d", &n, &m);int a = readln(A);int b = readln(B); readln(C);if (a != b) {puts("-1"); return 0;}for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++) {if (A[i][j] == 1) push(S, number(i, j, 0), 1, 0);if (B[i][j] == 1) push(number(i, j, 1), T, 1, 0);if (A[i][j] == 1 && B[i][j] == 1) push(number(i, j, 0), number(i, j, 1), (C[i][j]+2)/2, 1);else if (A[i][j] == 1 || B[i][j] == 1) push(number(i, j, 0), number(i, j, 1), (C[i][j]+1)/2, 1);else push(number(i, j, 0), number(i, j, 1), C[i][j]/2, 1);for (int k = 0; k < 8; k++) push(number(i, j, 1), number(i+dx[k], j+dy[k], 0), INF, 0);}int ans = 0, cost = 0;ans = mst(cost);if (ans == a) {cout << cost-a << endl;} elseputs("-1");return 0; }

    轉載于:https://www.cnblogs.com/ljt12138/p/6684333.html

    總結

    以上是生活随笔為你收集整理的[CQOI2012]交换棋子【网络流】【费用流】的全部內容,希望文章能夠幫你解決所遇到的問題。

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