有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态。要求第i行第j列的格子只能参与mi,j次交换。
#include
#include
#include
#define N 2000
#define M 50000
#define inf 707406378
using namespace std;
char map[40][40],p[50][50],s[50][50];
int n,m,T,dis[N],f[N],q[N*200],pre[N],c[50][50],sum1,sum2,ans;
int cnt(1),next[M<<1],point[N],num,ff,a[50][50],b[50][50];
int x[8]={1,0,-1,0,1,1,-1,-1},y[8]={0,1,0,-1,-1,1,-1,1};
struct use{
int st,en,v,c;
}e[M<<1];
void add(int x,int y,int v,int c){
next[++cnt]=point[x];point[x]=cnt;
e[cnt].st=x;e[cnt].en=y;e[cnt].v=v;e[cnt].c=c;
next[++cnt]=point[y];point[y]=cnt;
e[cnt].st=y;e[cnt].en=x;e[cnt].v=0;e[cnt].c=-c;
}
bool spfa(){
int h(0),t(1);
memset(dis,127/3,sizeof(dis));
memset(f,0,sizeof(f));
f[1]=1;dis[1]=0;q[t]=1;
while (hdis[u]+e[i].c){
pre[e[i].en]=i;dis[e[i].en]=dis[u]+e[i].c;
if (!f[e[i].en]){
f[e[i].en]=1;
q[++t]=e[i].en;
}
}
}
return dis[T]!=inf;
}
void isap(){
int mn=inf;
for (int i=T;i!=1;i=e[pre[i]].st) mn=min(mn,e[pre[i]].v);
num+=mn;
for (int i=T;i!=1;i=e[pre[i]].st){
e[pre[i]].v-=mn;e[pre[i]^1].v+=mn;ans+=mn*e[pre[i]].c;
}
}
int cal(int x,int y){return (x-1)*m+y-1;}
int main(){
scanf("%d%d",&n,&m);T=n*m*3+2;
for (int i=1;i<=n;i++) scanf("%s",map[i]+1);
for (int i=1;i<=n;i++) scanf("%s",p[i]+1);
for (int i=1;i<=n;i++) scanf("%s",s[i]+1);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
c[i][j]=s[i][j]-'0';
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++){
a[i][j]=map[i][j]-'0';
b[i][j]=p[i][j]-'0';
if (!a[i][j]) sum1++;
if (!b[i][j]) sum2++;
if ((!a[i][j])&&(!b[i][j])) sum1--,sum2--,a[i][j]=b[i][j]=1;
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++){
if (!a[i][j]){
add(cal(i,j)*3+3,cal(i,j)*3+2,(c[i][j])/2,0);
add(cal(i,j)*3+2,cal(i,j)*3+4,(c[i][j]+1)/2,0);
add(1,cal(i,j)*3+2,1,0);
}
if (!b[i][j]){
add(cal(i,j)*3+3,cal(i,j)*3+2,(c[i][j]+1)/2,0);
add(cal(i,j)*3+2,cal(i,j)*3+4,(c[i][j])/2,0);
add(cal(i,j)*3+2,T,1,0);
}
if (a[i][j]&&b[i][j]){
add(cal(i,j)*3+3,cal(i,j)*3+2,(c[i][j])/2,0);
add(cal(i,j)*3+2,cal(i,j)*3+4,(c[i][j])/2,0);
}
}
if (sum1!=sum2){return cout<<-1<n||xx<1||yy>m||yy<1) continue;
add(cal(i,j)*3+4,cal(xx,yy)*3+3,inf,1);
}
}
while (spfa()) isap();
if (num!=sum1){return cout<<-1<