#include <cstdio> #include <cstring> #include <iostream> #include <cmath> #include <algorithm> #include <queue> #include <vector> using namespace std; const int maxe = 100000; const int maxn = 205; const int INF = 0x3f3f3f3f; struct Edge{ int u,v,flow,cap,cost; int next; Edge(int u=0,int v=0,int flow=0,int cap=0,int cost=0,int next=0): u(u), v(v), flow(flow), cap(cap), cost(cost), next(next){} }; struct MCMF{ Edge edges[maxe]; int head[maxn],cnt; int d[maxn]; bool inq[maxn]; int pa[maxn]; int res[maxn]; void init(){ memset(head,-1,sizeof(head)); cnt = 0; } void addedge(int u,int v,int cap,int cost){ edges[cnt] = Edge(u,v,0,cap,cost,head[u]); head[u] = cnt++; edges[cnt] = Edge(v,u,0,0,-cost,head[v]); head[v] = cnt++; } bool SPFA(int s,int t,int& flow,int& cost){ memset(d,0x3f,sizeof(d)); memset(inq,0,sizeof(inq)); queue<int> Q; Q.push(s); inq[s] = true; d[s] = 0; res[s] = INF; res[t] = 0; while(!Q.empty()){ int u = Q.front(); Q.pop(); inq[u] = false; for(int i=head[u];i!=-1;i=edges[i].next){ Edge& e = edges[i]; if(e.cap>e.flow && d[e.v] > d[u] + e.cost){ d[e.v] = d[u] + e.cost; pa[e.v] = i; res[e.v] = min(res[u],e.cap-e.flow); if(!inq[e.v]){ Q.push(e.v); inq[e.v] = true; } } } } if(res[t] == 0) return false; flow += res[t]; cost += res[t]*d[t]; for(int i=t;i!=s;i=edges[pa[i]].u){ edges[pa[i]].flow += res[t]; edges[pa[i]^1].flow -= res[t]; } return true; } int MinCost(int s,int t){ int flow = 0,cost = 0; while(SPFA(s,t,flow,cost)){} return cost; } }solver; struct Node{ int x,y; int dist; Node(int x=0,int y=0,int dist = 0): x(x), y(y) ,dist(dist) {} }; Node Knight[35]; int n,k,m; int dist[35][105]; int Mymap[35][35]; // == 0代表rock,-1代表space ,1-m代表mill. int next_x[4] = {-1,0,1,0}; int next_y[4] = {0,-1,0,1}; void bfs(){ bool vis[35][35]; memset(dist,0x3f,sizeof(dist)); queue<Node> Q; for(int i=1;i<=k;i++){ while(!Q.empty()) Q.pop(); Q.push(Node(Knight[i].x,Knight[i].y,0)); memset(vis,0,sizeof(vis)); vis[Knight[i].x][Knight[i].y] = true; while(!Q.empty()){ Node out = Q.front(); Q.pop(); for(int j=0;j<4;j++){ int x = out.x + next_x[j]; int y = out.y + next_y[j]; if(vis[x][y]) continue; vis[x][y] = true; if(Mymap[x][y] == -1){ Q.push(Node(x,y,out.dist+1)); } else if(Mymap[x][y]>0){ dist[i][Mymap[x][y]] = out.dist+1; Q.push(Node(x,y,out.dist+1)); } } } } } int main() { //freopen("E:\acm\input.txt","r",stdin); int T; cin>>T; for(int cas=1;cas<=T;cas++){ cin>>n>>k>>m; char ch[35]; memset(Mymap,0,sizeof(Mymap)); int cntm = 1; for(int i=1;i<=n;i++){ scanf("%s",ch+1); for(int j=1;j<=n;j++){ if(ch[j]>='A' && ch[j]<='Z'){ int num = ch[j] - 'A' + 1; Knight[num] = Node(i,j,0); Mymap[i][j] = -1; } else if(ch[j] == 'm'){ Mymap[i][j] = cntm++; } else if(ch[j] == '.'){ Mymap[i][j] = -1; } } } bfs(); solver.init(); int s = 0, t = k+m+1; for(int i=1;i<=k;i++){ int a; scanf("%d",&a); solver.addedge(s,i,a,0); } for(int i=1;i<=k;i++) for(int j=1;j<=m;j++){ solver.addedge(i,k+j,1,dist[i][j]); } for(int i=1;i<=m;i++){ solver.addedge(k+i,t,1,0); } printf("Case %d: %d ",cas,solver.MinCost(s,t)); } }