
‘A’ : Representative of watchtower, which has an attack range of 2(measured by Manhattan distance),and an attack damage of 1.
‘B’ : Representative of Fort, which has an attack range of 3(measured by Manhattan distance),and an attack damage of 2.
‘C’ : Representative of Flame, which has an attack damage of 3 to those who step onto it.
‘D’ : Representative of Archer, which has anattack range of 2(measured by Manhattan distance), and an attack damage of 4.
‘E’ : Representative of Ordinary soldier, which has anattack range of 1(measured by Manhattan distance), and an attack damage of 5.
‘$’ : Representative of Liu Bei.
‘!’ : Representative of Destination.
'#' : Representative of obstacles
‘.’ : Representative of floor.
Liu Bei can not enter watchtower, forts, Archers, ordinary soldiers,But he can step onto flame or floor.
Some important rules you should note:
1. Liu Bei will not be hurt by the same thing twice.For example,if Liu Bei has been hurt by one watchtower before,then he step into the attack range of some watchtower later,he will not be hurt.
2. When Liu Bei reach the destination,you should first judge the attack damage at the destination then finish the game.
3. You needn’t judge the attack damage at the start position.
Please choose a path which LiuBei would cost the least HP.
In each case,the first line of the input contains two integer n,m(1<=n,m<=50),reperesenting the size of map(n*m).Then follow n lines,each line contain m characters.
There may be some blank lines between each case.
1 4 3 .$. ACB ACB .!.
Case 1: 6
//
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=10000;
struct Node
{
int x,y;
int hurt;
int vis[10];//受伤害情况
friend bool operator <(Node h,Node k)
{
return h.hurt>k.hurt;
}
};
int n,m;
char str[60][60];
int atk[60][60][10];//1:x,y能被attack攻击
int mark[60][60];//
Node st,ed;
int xx[4]={0,0,1,-1};
int yy[4]={1,-1,0,0};
int hurt[5]={1,2,3,4,5};
int judge(int x,int y,int vis[10])
{
int ans=0;
for(int i=0;i<5;i++)
{
if(atk[x][y][i]&&vis[i]==0)
{
ans+=hurt[i];
vis[i]=1;
}
}
return ans;
}
int OK(int x,int y)//in frame
{
if(x>=0&&x<n&&y>=0&&y<m) return 1;
return 0;
}
void dfs(int x,int y,int step,int attack)//攻击范围
{
atk[x][y][attack]=1;
if(step==0) return ;//注意这句话的位置
for(int i=0;i<4;i++)
{
int tx=x+xx[i],ty=y+yy[i];
if(OK(tx,ty)) dfs(tx,ty,step-1,attack);
}
}
int BFS()
{
memset(st.vis,0,sizeof(st.vis));
priority_queue<Node> q;
Node cur,nxt,tmp;
q.push(st);
memset(mark,0,sizeof(mark));
mark[st.x][st.y]=1;
while(!q.empty())
{
cur=q.top();q.pop();
if(cur.x==ed.x&&cur.y==ed.y) return cur.hurt;
for(int i=0;i<4;i++)
{
nxt.x=cur.x+xx[i],nxt.y=cur.y+yy[i];
if(!OK(nxt.x,nxt.y)||mark[nxt.x][nxt.y]) continue;
memcpy(nxt.vis,cur.vis,sizeof(cur.vis));
if(str[nxt.x][nxt.y]=='C'||str[nxt.x][nxt.y]=='.')
{
mark[nxt.x][nxt.y]=1;
nxt.hurt=cur.hurt+judge(nxt.x,nxt.y,nxt.vis);
q.push(nxt);
}
else if(str[nxt.x][nxt.y]=='!')
{
// mark[nxt.x][nxt.y]=1; 这里不一定是最优解
nxt.hurt=cur.hurt+judge(nxt.x,nxt.y,nxt.vis);
q.push(nxt);
}
}
}
return -1;
}
int main()
{
int ci,pl=1;scanf("%d",&ci);
while(ci--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++) scanf("%s",str[i]);
memset(atk,0,sizeof(atk));
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(str[i][j]=='$')
{
st.x=i,st.y=j;
st.hurt=0;
}
else if(str[i][j]=='!')
{
ed.x=i,ed.y=j;
}
else if(str[i][j]=='A')
{
dfs(i,j,2,0);
}
else if(str[i][j]=='B')
{
dfs(i,j,3,1);
}
else if(str[i][j]=='C')
{
dfs(i,j,0,2);
}
else if(str[i][j]=='D')
{
dfs(i,j,2,3);
}
else if(str[i][j]=='E')
{
dfs(i,j,1,4);
}
}
}
int ans=BFS();
printf("Case %d: %d\n",pl++,ans);
}
return 0;
}