//本题要用到bfs和dfs两种搜索;
//用bfs的目的就是寻找最短路径(把点存在了队列中);
//寻找起点,终点,财宝,两两之间的距离,最后存在dp数组中;
//dfs作用就是搜索从起点到终点;
//在time允许的情况下,所能携带最多的财富;
#include"stdio.h"
#include"string.h"
#include"queue"
using namespace std;
char map[100][100];
int visit[100][100],a[100];
int step[100][100],mark[100];
int dp[100][100];
int w,h,l,m,maxx,sum;
int dir[4][2]={-1,0, 1,0, 0,1, 0,-1};
int judge(int x,int y)
{
if(x>=0&&x<w&&y>=0&&y<h&&map[x][y]!='*')
return 1;
return 0;
}
void bfs(int x,int y,int n)
{
int i;
memset(visit,0,sizeof(visit));
memset(step,0,sizeof(step));
queue<int>q;
int u=x*h+y;
visit[x][y]=1;
step[x][y]=0;
q.push(u);
while(!q.empty())
{
u=q.front();
q.pop();
x=u/h;
y=u%h;
for(i=0;i<4;i++)
{
int xx=x+dir[i][0];
int yy=y+dir[i][1];
step[xx][yy]=step[x][y]+1;
if(judge(xx,yy)&&visit[xx][yy]==0)
{
if(map[xx][yy]=='@')
dp[n][0]=step[xx][yy];
else if(map[xx][yy]=='<')
dp[n][m+1]=step[xx][yy];
else if(map[xx][yy]>='A'&&map[xx][yy]<='J')
dp[n][map[xx][yy]-'A'+1]=step[xx][yy];
visit[xx][yy]=1;
q.push(xx*h+yy);
}
}
}
}
void dfs(int now,int v,int time)
{
if(time>l)
return ;
if(maxx==sum)
return ;
if(now>m)
{
if(v>maxx)
maxx=v;
return;
}
int i;
for(i=0;i<=m+1;i++)
{
if(dp[now][i]&&mark[i]==0)
{
mark[i]=1;
dfs(i,v+a[i],time+dp[now][i]);
mark[i]=0;
}
}
}
int main()
{
int i,j,k,r=1,t;
scanf("%d",&k);
for(t=1;t<=k;t++)
{
sum=0;
memset(mark,0,sizeof(mark));
memset(dp,0,sizeof(dp));
scanf("%d%d%d%d",&h,&w,&l,&m);
for(i=1;i<=m;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
}
a[0]=a[m+1]=0;
for(i=0;i<w;i++)
scanf("%s",map[i]);
for(i=0;i<w;i++)
for(j=0;j<h;j++)
{
if(map[i][j]=='@')
{
bfs(i,j,0);
}
else if(map[i][j]=='<')
{
bfs(i,j,m+1);
}
else if(map[i][j]>='A'&&map[i][j]<='J')
{
bfs(i,j,map[i][j]-'A'+1);
}
}
mark[0]=1;maxx=-1;dfs(0,0,0);
if(t!=1)
printf("\n");
printf("Case %d:\n",r++);
if(maxx!=-1)
printf("The best score is %d.\n",maxx);
else
printf("Impossible\n");
}
return 0;
}