/*
HDOJ1044 BFS+DFS
把起点@,终点<,各个分值点A~J 作为目标点,分别对各个点DFS得到各个点对的最近距离
再用BFS,从起点到终点,经过各个分值点在时间限制内所能得到的最优值
遗留问题一:
说好的用Floyd代替BFS求最优值自己实现不出来。。。。
遗留问题二:
为啥 用 dist[0][k+1]>t 作为终止条件就是错的 !!!!求大神指教
*/
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <cstring>
#include <sstream>
#include <queue>
#include <stack>
using namespace std;
#define input freopen("input.txt","r",stdin)
#define output freopen("output.txt","w",stdout)
#define For1(i,a,b) for (i=a;i<b;i++)
#define For2(i,a,b) for (i=a;i<=b;i++)
#define Dec(i,a,b) for (i=a;i>b;i--)
#define Dec2(i,a,b) for (i=a;i>=b;i--)
#define Sca_d(x) scanf("%d",&x)
#define Sca_s(x) scanf("%s",x)
#define Sca_c(x) scanf("%c",&x)
#define Sca_f(x) scanf("%f",&x)
#define Sca_lf(x) scanf("%lf",&x)
#define Fill(x,a) memset(x,a,sizeof(x))
#define MAXN 0x7fffffff
int n,m,k;
int score[150];
int dist[200][200];
char Map[550][550],in[550];
int dir_x[]={0,1,-1,0,0};
int dir_y[]={0,0,0,1,-1};
int vis[55],sum,ans,t;
void bfs(int tx,int ty,int num)
{
int head=1,tail=1,dir,nx,ny;
int steps[55][55],visit[55][55];
struct
{
int x,y;
}que[2555];
Fill(steps,0);Fill(visit,0);Fill(que,0);
que[head].x=tx;
que[head].y=ty;
visit[tx][ty]=1;
while(head<=tail)
{
For2(dir,1,4)
{
nx=que[head].x+dir_x[dir],ny=que[head].y+dir_y[dir];
if (nx>=0&&nx<n&&ny>=0&&ny<m&&!visit[nx][ny]&&Map[nx][ny]!='*')
{
steps[nx][ny]=steps[que[head].x][que[head].y]+1;
tail++;
que[tail].x=nx;
que[tail].y=ny;
visit[nx][ny]=1;
if (Map[nx][ny]>='A'&&Map[nx][ny]<='J')
dist[num][Map[nx][ny]-'A'+1]=steps[nx][ny];
else if (Map[nx][ny]=='@')
dist[num][0]=steps[nx][ny];
else if (Map[nx][ny]=='<')
dist[num][k+1]=steps[nx][ny];
}
}
head++;
}
}
void dfs(int s,int value,int time)
{
int i;
if(time>t) return;//超出限制时间
if(ans==sum) return;//已经得到了最大的价值,剪枝(没有这个会超时)
//借鉴的kuangbin大神的高级思路!
if(s==k+1)
{
if(value>ans) ans=value;
return;
}
For2(i,1,k+1)
{
if(dist[s][i]==0||vis[i]) continue;
vis[i]=true;
dfs(i,value+score[i],time+dist[s][i]);
vis[i]=false;
}
}
int main()
{
//input;
int i,j,Case;
cin>>Case;
for(int Case_num=1;Case_num<=Case;Case_num++)
{
getchar();
Fill(score,0);Fill(dist,0);Fill(score,0);Fill(Map,0);Fill(vis,0);sum=0,ans=-1;
//一切有用的东西赋初值!
cin>>m>>n>>t>>k;
For2(i,1,k) Sca_d(score[i]),sum+=score[i];//输入分值的和时,顺便计算所有分值的和。方便剪枝
For2(i,0,n-1)
{
Sca_s(in);
For2(j,0,m-1)
Map[i][j]=in[j];
}
For2(i,0,n-1)
For2(j,0,m-1)
if ((Map[i][j]>='A'&&Map[i][j]<='J'))
bfs(i,j,Map[i][j]-'A'+1);//A表示为1,依次类推
else if (Map[i][j]=='@')
bfs(i,j,0);//起点标号为0
/*For2(i,0,k)
{
For2(j,0,k+1)
printf("%d ",dist[i][j]);
cout<<endl;
}
cout<<endl;*/
//写DFS为了检验BFS的正确性作的中间过程输出
printf("Case %d:\n",Case_num);
dfs(0,0,0);
if (ans>=0) printf("The best score is %d.\n",ans);
else printf("Impossible\n");
/*if (dist[0][k+1]>t) printf("Impossible\n");
//不理解用 dist[0][k+1] 作为判断条件为啥WA!!!!
else
{
dfs(0,0,0);
printf("The best score is %d.\n",ans);
}*/
if (Case_num<Case) cout<<endl;
}
return 0;
}
//ans=dfs(startx,starty);
/*For2(i,1,k+1)
if (dist[0][i]&&dist[0][i]<=t)
dp[i]=score[i],dp_dis[i]=dist[0][i];
int kk=0;
For2(kk,0,k+1)
For2(i,0,k+1)
if (dist[kk][i])
For2(j,0,k+1)
if (dist[i][j])
if (dist[kk][i]+dist[i][j]<=t)
{
if (dp[i]+dp[j]>=dp[j])
dp[j]=dp[i]+dp[j],dp_dis[j]=dist[kk][i]+dist[i][j];
else if (dp[j]==dp[i]+dp[j]&&dp_dis[j]<dist[kk][i]+dist[i][j])
dp_dis[j]=dist[kk][i]+dist[i][j];
}*/
/*For2(i,0,k+1)
{
For2(j,0,k+1)
printf("%d ",dist[i][j]);
cout<<endl;
}
cout<<endl;*/
//这里是自己想实现的Floyd求最优值,总是WA。。。。