bzoj2668 cqoi2012 交換棋子

2022-08-23 04:54:06 字數 2741 閱讀 4935

description

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

input

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

output

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

sample input

3 3

110

000

001

000

110

100

222

222

222sample output

4分析:

題面讓人覺得很奇怪

實際上我們可以看做只有黑棋子,這樣就好處理多了

說實話,這道題的建圖是我見過的最zz的

顯然初始狀態和最終狀態該位置都是黑棋時,

這個黑棋是沒有必要移動的,對答案沒有貢獻

所以我們就可以把ta變成白棋

題目的限制不是在棋子上,而是在格仔上

我們把每個格仔拆成三個點a,b,c

(1)格仔的初始狀態是1,連線(s,a,1,0),(b,a,m[i][j]/2,0),(a,c,(m[i][j]+1)/2,0)

(2)格仔末狀態是1,連線(a,t,1,0),(b,a,(m[i][j]+1)/2,0),(a,c,m[i][j]/2,0)

(3)始末都是0,連線(b,a,m[i][j]/2,0),(a,c,m[i][j]/2,0)

(4)相鄰格仔x,y,連線(xc,yb,inf,1)

解釋 對於一次交換,會使用相鄰兩個格仔各一次,一共會使用兩次,

所以我們將邊權除以二

對於初始黑子在的點,與末尾黑子在的點,

其實對於這個黑子只用交換一次,所以只會使用1的流量,

所以我們把ta的邊權令為(m[i][j]+1)/2,這個細節比較重要

附測試樣例及圖

發現自己的spfa都寫不好了

在獲取點的編號的時候,get函式中n和m不要弄混了

手殘黨。。。sto

這裡寫**片

#include

#include

#include

using namespace std;

const int inf=0x33333333;

const int n=50010;

int st[n],tot=-1,s,t;

struct node;

node way[n<<2];

int pre[n],dis[n],q[n],tou,wei;

bool p[n];

int mp[100][100],num[100][100],n,m;

int get(int

x,int

y)void add(int u,int w,int v,int cc)

int spfa(int

s,int t)

}p[r]=1;

}while (toureturn dis[t]!=inf;

}void doit()

printf("%d",ans);

}void lianbian()

else

if (mp[i][j]==2)

else

if (i+1

<=n) add(get(i,j)+n*m

*2,get(i+1,j)+n*m,inf,1);

if (j+1

<=m) add(get(i,j)+n*m

*2,get(i,j+1)+n*m,inf,1);

if (i-1>0) add(get(i,j)+n*m

*2,get(i-1,j)+n*m,inf,1);

if (j-1>0) add(get(i,j)+n*m

*2,get(i,j-1)+n*m,inf,1);

if (i+1

<=n&&j+1

<=m) add(get(i,j)+n*m

*2,get(i+1,j+1)+n*m,inf,1);

if (i-1>0&&j-1>0) add(get(i,j)+n*m

*2,get(i-1,j-1)+n*m,inf,1);

if (i+1

<=n&&j-1>0) add(get(i,j)+n*m

*2,get(i+1,j-1)+n*m,inf,1);

if (i-1>0&&j+1

<=m) add(get(i,j)+n*m

*2,get(i-1,j+1)+n*m,inf,1);

}}int main()

}for (int i=1;i<=n;i++)

}for (int i=1;i<=n;i++)

if (cnt!=0)

lianbian();

doit();

return

0;}

BZOJ 2668 cqoi2012 交換棋子

time limit 3 sec memory limit 128 mb submit 1112 solved 409 submit status discuss 有乙個n行m列的黑白棋盤,你每次可以交換兩個相鄰格仔 相鄰是指有公共邊或公共頂點 中的棋子,最終達到目標狀態。要求第i行第j列的格仔只能...

BZOJ2668 cqoi2012 交換棋子

題解 可以戳這裡 其實自己yy一下就知道這樣建圖的正確性了。感覺太神奇,居然還能拆成3個點 orzzzzzzzzzzzzzzzzzzzzzzzzz 跪跪跪跪跪跪跪跪 1 include2 3 include4 5 include6 7 include8 9 include10 11 include1...

bzoj2668 cqoi2012 交換棋子

description 有乙個 n 行 m 列的黑白棋盤,你每次可以交換兩個相鄰格仔 相鄰是指有公共邊或公共頂點 中的棋子,最終達到目標狀態。要求第 i 行第 j 列的格仔只能參與 m 次交換。input 第一行包含兩個整數 n,m 1 le n,m le 20 以下 n 行為初始狀態,每行為乙個包...