题目大意:迷宫问题。在一个h * w的地图上,@代表起始位置,"."代表空地,"<"代表出口,"A"-"J"代表不同的宝物,不同的宝物有不同的价值,给定一个时间l,要求在l的时间内走出这个迷宫,并要带走最大价值的宝物,求最优解,无法逃出迷宫输出“Impossible”。
题目分析:既然明显是迷宫问题,肯定要搜索。但这题不是简单的要求逃出迷宫就行了,还要求尽可能的带走价值最大的宝物,而宝物的相对位置未知,所以盲目的搜索会产生大量的重复搜索量,所以先bfs求出各宝物以及起点、终点的相对位置,宝物不超过10个,然后再进行dfs遍历所有可能的情况,取最优解即可,这样可以省略大量的无用搜索步骤,节省时间。详情请见代码:
#include <iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<cstring>
using namespace std;
const int N = 51;
#define INF 0x3f3f3f3f
char graph[N][N];
int h,w,l,m,sum;
int si,sj,ei,ej;
int ans,ok;
int value[15];
int dis[N][N];
//起点、终点以及各珠宝之间的距离,0代表起点,1-m代表m种珠宝,m + 1代表终点
int dir[][2] = {{0,1},{0,-1},{1,0},{-1,0}};
bool flag[N][N];
bool vis[15];
struct node
{
int i,j,step;
}s,now;
queue<struct node>lcm;
int min(int a,int b)
{
return a > b?b:a;
}
void dfs(int cur,int time,int cal)
{
if(time < 0)
return;
if(ans == sum)
return;
if(cur == m + 1)
{
if(ans < cal)
ans = cal;
return;
}
int i;
for(i = 1;i <= m + 1;i ++)
{
if(!vis[i])
{
vis[i] = 1;
dfs(i,time - dis[cur][i],cal + value[i - 1]);
vis[i] = 0;
}
}
}
void bfs()
{
while(!lcm.empty())
lcm.pop();
//printf("%c\n",graph[s.i][s.j]);
int i;
int start;
if(graph[s.i][s.j] == '@')
start = 0;
else
{
start = graph[s.i][s.j] - 64;
}
dis[start][start] = 0;
s.step = 0;
lcm.push(s);
memset(flag,0,sizeof(flag));
flag[s.i][s.j] = 1;
while(!lcm.empty())
{
now = lcm.front();
lcm.pop();
for(i = 0;i < 4;i ++)
{
s = now;
s.i += dir[i][0];
s.j += dir[i][1];
if(s.i >= h || s.i < 0 || s.j >= w || s.j < 0)
continue;
if(graph[s.i][s.j] == '*' || flag[s.i][s.j])
continue;
s.step = now.step + 1;
if(graph[s.i][s.j] == '<')
{
dis[start][m + 1] = min(dis[start][m + 1],s.step);
dis[m + 1][start] = dis[start][m + 1];
}
else
{
if(graph[s.i][s.j] >= 'A' && graph[s.i][s.j] <= 'J')
{
dis[start][graph[s.i][s.j] - 64] = min(dis[start][graph[s.i][s.j] - 64],s.step);
dis[graph[s.i][s.j] - 64][start] = dis[start][graph[s.i][s.j] - 64];
}
}
lcm.push(s);
flag[s.i][s.j] = 1;
}
}
}
int main()
{
int i,j,t;
int cas = 0;
scanf("%d",&t);
while(t --)
{
sum = 0;
scanf("%d%d%d%d",&w,&h,&l,&m);
for(i = 0;i < m;i ++)
{
scanf("%d",&value[i]);
sum += value[i];
}
value[m] = 0;
getchar();
for(i = 0;i < h;i ++)
scanf("%s",graph[i]);
memset(dis,0x3f,sizeof(dis));
for(i = 0;i < h;i ++)
{
for(j = 0;j < w;j ++)
{
if(graph[i][j] == '*')
continue;
if(graph[i][j] == '@')
{
si = i;
sj = j;
s.i = i;
s.j = j;
bfs();
//printf("@isok\n");
}
else
{
if(graph[i][j] >= 'A' && graph[i][j] <= 'Z')
{
s.i = i;
s.j = j;
bfs();
//printf("%cisok\n",graph[i][j]);
}
else
{
if(graph[i][j] == '<')
{
ei = i;
ej = j;
}
else
continue;
}
}
}
}
printf("Case %d:\n",++cas);
if(dis[0][m + 1] > l)
{
printf("Impossible\n");
if(t)
printf("\n");
continue;
}
ans = 0;
/*for(i = 0;i <= m + 1;i ++)
{
for(j = 0;j <= m + 1;j ++)
printf("%d ",dis[i][j]);
printf("\n");
}*/
memset(vis,0,sizeof(vis));
vis[0] = 1;
dfs(0,l,0);
printf("The best score is %d.\n",ans);
if(t)
printf("\n");
}
return 0;
}
//31MS 380K