解题思路:
建立一个流量网络,一个二部图。X部分向Y部分链接的情况表示可以从一个点跳到另一个点,超级源点和超级汇点分别同X部分的点和Y部分的点链接。在X部分中多加一个点它与源点的流量是K费用是0,与Y部分所有点链接流量是1费用是0。这表示操作K次。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define rep(i,a,b) for (int i=a;i<(b+1);i++)
using namespace std;
const int maxn=250;
const int inf=1<<29;
const int maxm=maxn*maxn*5;
int n,m,k,st,end,head[maxn]={0},pnt[maxm],cnt,nxt[maxm],cost[maxm],flow[maxm],pre[maxn],dis[maxn];
char s[maxn][maxn];
void addedge(int u,int v,int c,int f){
pnt[cnt]=v;nxt[cnt]=head[u];cost[cnt]=c;flow[cnt]=f;head[u]=cnt++;
pnt[cnt]=u;nxt[cnt]=head[v];cost[cnt]=-c;flow[cnt]=0;head[v]=cnt++;
}
bool spfa(){
bool vis[maxn]={false};
rep(i,st,end+1){
pre[i]=-1;
dis[i]=inf;
}
dis[st]=0;
queue<int> q;
vis[st]=true;
q.push(st);
while (!q.empty()){
int u=q.front();
q.pop();
for (int i=head[u];i!=-1;i=nxt[i])
if (flow[i]&&dis[u]+cost[i]<dis[pnt[i]]){
dis[pnt[i]]=dis[u]+cost[i];
pre[pnt[i]]=i;
if (!vis[pnt[i]]){
q.push(pnt[i]);
vis[pnt[i]]=true;
}
}
vis[u]=false;
}
return dis[end]!=inf;
}
void Build(){
cnt=0;
memset(pnt,0,sizeof pnt);
memset(nxt,0,sizeof nxt);
memset(cost,0,sizeof cost);
memset(flow,0,sizeof flow);
st=0,end=2*n*m+1;
int p=2*n*m+2;
memset(head,-1,sizeof head);
addedge(st,p,0,k);
rep(i,1,n*m){
addedge(st,i,0,1);
addedge(n*m+i,end,0,1);
addedge(p,n*m+i,0,1);
}
rep(i,0,n-1) rep(j,0,m-1){
rep(k,j+1,m-1)
if (s[i][j]==s[i][k]) addedge(i*m+j+1,n*m+i*m+k+1,-(s[i][j]-'0'-(k-j-1)),1);
else addedge(i*m+j+1,n*m+i*m+k+1,k-j-1,1);
rep(k,i+1,n-1)
if (s[i][j]==s[k][j]) addedge(i*m+j+1,n*m+k*m+j+1,-(s[i][j]-'0'-(k-i-1)),1);
else addedge(i*m+j+1,n*m+k*m+j+1,k-i-1,1);
}
}
void mincostflow(){
int ans=0,sum=0;
while (spfa()){
int mini=inf;
for (int i=pre[end];i!=-1;i=pre[pnt[i^1]]) mini=min(mini,flow[i]);
for (int i=pre[end];i!=-1;i=pre[pnt[i^1]]){
flow[i]-=mini;
flow[i^1]+=mini;
}
sum+=mini;
ans+=dis[end]*mini;
}
if (sum==n*m) printf("%d\n",-ans);
else printf("-1\n");
}
int main(){
int T;
scanf("%d",&T);
rep(z,1,T){
scanf("%d%d%d",&n,&m,&k);
rep(i,0,n-1) scanf("%s",s[i]);
printf("Case %d : ",z);
Build();
mincostflow();
}
return 0;
}