有乙個n行
m列的黑白棋盤,你每次可以交換兩個相鄰格仔(相鄰是指有公共邊或公共頂點)中的棋子,最終達到目標狀態。要求第i行第j列的格仔只能參與mi
,j次交換。
第一行包含兩個整數n,
m(1≤
n,m≤
20)。以下n
行為初始狀態,每行為乙個包含
m個字元的
01串,其中
0表示黑色棋子,
1表示白色棋子。以下
n行為目標狀態,格式同初始狀態。以下n行每行為乙個包含m個
0..9
數字的字串,表示每個格仔參與交換的次數上限。
輸出僅一行,為最小交換總次數。如果無解,輸出−1
。一眼費用流系列…然而這題的處理有點詭異,首先要拆點將點的限制轉化為邊的限制,s→
ini,
outi
→t。i
n→ou
t的權值是多少?分三種情況討論:
既不是起始也不是結束狀態:⌊n
2⌋既是起始也是結束狀態:⌊n
+22⌋
是起始或結束狀態:⌊n
+12⌋
#include
using
namespace
std;
const
int maxn = 2005;
struct node edge[maxn*40];
int head[maxn], top = 0;
void push(int i, int j, int k, int l)
, head[i] = top;
++top, edge[top] = (node) , head[j] = top;
}int vis[maxn], dis[maxn], s = 2001, t = 2002;
queue
que;
int pre[maxn], pre_edge[maxn];
const
int inf = 233333333;
bool spfa()
}return dis[t] < inf;
}int sap(int &cost)
int mst(int &cost)
int n, m;
int a[30][30], b[30][30], c[30][30];
char str[30];
int readln(int a[30][30])
return cnt;
}inline
int number(int i, int j, int id)
int dx = , dy = ;
int main()
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
int ans = 0, cost = 0;
ans = mst(cost);
if (ans == a) else
puts("-1");
return
0;}
CQOI2012 交換棋子 費用流
有乙個n行m列的黑白棋盤,你每次可以交換兩個相鄰格仔 相鄰是指有公共邊或公共頂點 中的棋子,最終達到目標狀態。要求第i行第j列的格仔只能參與mi,j次交換。乙個點拆三份,入點,主點,出點 入點向主點連邊,主點向出點連邊,設該點允許的交換次數為 x 根據以下規則確定 s to 初態點,末態點 to t...
題解 CQOI2012交換棋子
感受到網路流的強大了 這道題目的關鍵在於 前後顏色不變的,流入流出的次數相等 原本是黑色的最後變成了白色,流出比流入次數多1 原本是白色最後變成黑色,流入比流出次數多一。所以我們將每一點拆成3個點,分別代表流入點,原點與流出點。最開始為黑色的點與源點連流量為1,費用為0的邊,最後為黑色的點與匯點連流...
CQOI2012 交換棋子(拆點 費用流)
注意相鄰交換指的是八連通 顯然可以將黑白交換看做只有黑色棋子在空棋盤上移動 交換限制交給流量,那麼有代價自然就是費用流了 考慮直接將兩個相鄰格仔連起來,由於交換次數是相對單個格仔而言的,流量無法確定 既然交換次數是單個格仔的屬性,自然可以考慮到拆點來表示其屬性 考慮將乙個格仔拆成入點和出點,中間連一...