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 行為初始狀態,每行為乙個包...