之前也是看的解题报告写的,所以写的不好。现在回头看看,其实很简单。
这篇我只作为笔记使用
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <math.h>
#include <queue>
#include <set>
#include <algorithm>
#include <stdlib.h>
using namespace std;
#define ll int
#define N 220
#define M 12345
#define inf (1<<29)
//注意 点标必须是 [0 - 汇点]
//双向边,注意RE
struct Edge{
ll from, to, flow, cap, nex, cost;
}edge[M*2];
ll head[N], edgenum;
void add(ll u,ll v,ll cap,ll cost){//网络流要加反向弧
Edge E={u, v, 0, cap, head[u], cost};
edge[edgenum]=E;
head[u]=edgenum++;
Edge E2={v, u, 0, 0, head[v], -cost}; //这里的cap若是单向边要为0
edge[edgenum]=E2;
head[v]=edgenum++;
}
ll D[N], P[N], A[N];
bool inq[N];
bool BellmanFord(ll s, ll t, ll &flow, ll &cost){
for(ll i=0;i<=t;i++) D[i]= inf;
memset(inq, 0, sizeof(inq));
D[s]=0; inq[s]=1; P[s]=0; A[s]=inf;
queue<ll> Q;
Q.push( s );
while( !Q.empty()){
ll u = Q.front(); Q.pop();
inq[u]=0;
for(ll i=head[u]; i!=-1; i=edge[i].nex){
Edge &E = edge[i];
if(E.cap > E.flow && D[E.to] > D[u] +E.cost){
D[E.to] = D[u] + E.cost ;
P[E.to] = i;
A[E.to] = min(A[u], E.cap - E.flow);
if(!inq[E.to]) Q.push(E.to) , inq[E.to] = 1;
}
}
}
if(D[t] == inf) return false;
flow += A[t];
cost += D[t] * A[t];
ll u = t;
while(u != s){
edge[P[u]].flow += A[t];
edge[P[u]^1].flow -= A[t];
u = edge[P[u]].from;
}
return true;
}
ll flow;
ll Mincost(ll s,ll t){//返回最小费用
flow = 0 ; ll cost = 0;
while(BellmanFord(s, t, flow, cost));
return cost;
}
void init(){memset(head,-1,sizeof head); edgenum = 0;}
ll n, m, k;
ll Hash1(ll x, ll y){ return (x-1)*m+y;}
ll Hash2(ll x, ll y){ return n*m + (x-1)*m+y; }
char s[20];
ll mp[20][20];
int main(){
int T, i, j, g, Cas = 1; scanf("%d",&T);
while(T--){
cin>>n>>m>>k;
for(i = 1; i <= n; i++)
{
scanf("%s",s+1);
for(j = 1; j<=m; j++)
mp[i][j] = s[j] - '0';
}
printf("Case %d : ", Cas++);
init();
ll i, j, g;
ll from = 0, to = Hash2(n,m)+10, jiji = to-2;
for(i = 1; i <= n; i++)
{
for(j = 1; j <= m; j++)
{
add(from, Hash1(i,j), 1, 0);
add(Hash2(i,j), to, 1, 0);
add(jiji, Hash2(i,j), 1, 0);
for(g = j+1; g <= m; g++)
{
ll cos = g - j - 1;
if(mp[i][j] == mp[i][g]) cos -= mp[i][j];
add(Hash1(i,j), Hash2(i, g), 1, cos);
}
for(g = i+1; g <= n; g++)
{
ll cos = g - i - 1;
if(mp[i][j] == mp[g][j]) cos -= mp[i][j];
add(Hash1(i,j), Hash2(g, j), 1, cos);
}
}
}
add(from, jiji, k, 0);
ll ans = - Mincost(from, to);
if(flow != n*m)
puts("-1");
else
cout<< ans << endl;
}
return 0;
}