题目比一般的图类的题目稍微绕了点弯子。要根据问题建立解题所需要的图。起始点@和终止点<以及Jewels点共同构成图的点,其之间的最短路径构成了图的边。根据新构成的图,利用深度优先进行解题就可以了。我的解法采用maze存储原问题的图。使用map数组存储最终创建的图,其中记录了临接点和路径长度(map[0].index记录了临接点的个数,其余点的index记录了存储在jewels中Jewel的索引)。建立图的时候,反复进行宽度优先搜索,将临接点存储到map中。然后对map进行深度优先搜索就可以了。
#include<queue>
using namespace std;
#include<stdio.h>
int width,height,jewelsNum;
struct Point{
int col,row,value;
};
struct Map{
int index,step;
};
Point jewels[12];
bool mapVisited[12];
Map map[12][12];
char maze[51][51];
const int choice[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int result,sumValue;
char target;
inline void init()
{
int assist;
sumValue=0;
for(int i=1;i<=jewelsNum;i++)
{
scanf("%d",&jewels[i].value);
sumValue+=jewels[i].value;
}
jewelsNum+=1;
target=jewelsNum+'A';
for(int i=0;i<height;i++)
{
getchar();
for(int j=0;j<width;j++)
{
scanf("%c",&maze[i][j]);
if(maze[i][j]=='@')
{
maze[i][j]='A';
jewels[0].row=i;
jewels[0].col=j;
jewels[0].value=0;
}
else if(maze[i][j]=='<')
{
maze[i][j]=target;
jewels[jewelsNum].row=i;
jewels[jewelsNum].col=j;
jewels[jewelsNum].value=0;
}
else if(maze[i][j]>='A'&&maze[i][j]<='J')
{
maze[i][j]+=1;
assist=maze[i][j]-'A';
jewels[assist].row=i;
jewels[assist].col=j;
}
}
}
}
inline bool check(int r,int c)
{
return r<0||r>=height||c<0||c>=width;
}
inline void buildMap()
{
bool visited[51][51];
for(int i=0;i<=jewelsNum;i++)
{
memset(visited,0,sizeof(visited));
map[i][0].index=0;
visited[jewels[i].row][jewels[i].col]=true;
queue<Point> que;
que.push(jewels[i]);
que.front().value=0;
while(!que.empty())
{
Point newPoint;
for(int j=0;j<4;j++)
{
newPoint.row=que.front().row+choice[j][0];
newPoint.col=que.front().col+choice[j][1];
if(check(newPoint.row,newPoint.col)||maze[newPoint.row][newPoint.col]=='*'
||visited[newPoint.row][newPoint.col]) continue;
visited[newPoint.row][newPoint.col]=true;
newPoint.value=que.front().value+1;
que.push(newPoint);
if(maze[newPoint.row][newPoint.col]!='.')
{
map[i][0].index++;
map[i][map[i][0].index].index=maze[newPoint.row][newPoint.col]-'A';
map[i][map[i][0].index].step=newPoint.value;
}
}
que.pop();
}
}
}
void solve(int depth,int limit,int max)
{
int row,col;
for(int i=1;i<=map[depth][0].index;i++)
{
row=jewels[map[depth][i].index].row;
col=jewels[map[depth][i].index].col;
if(map[depth][i].step>limit||(map[depth][i].step==limit&&maze[row][col]!=target)||mapVisited[map[depth][i].index]||maze[row][col]=='*') continue;
if(result==sumValue) return ;
if(maze[row][col]==target&&max>=result)
result=max;
mapVisited[map[depth][i].index]=true;
solve(map[depth][i].index,limit-map[depth][i].step,max+jewels[map[depth][i].index].value);
mapVisited[map[depth][i].index]=false;
}
}
int main()
{
//freopen("Collect More Jewels.txt","r",stdin);
int caseNum,limit;
scanf("%d",&caseNum);
for(int i=1;i<=caseNum;i++)
{
scanf("%d%d%d%d",&width,&height,&limit,&jewelsNum);
init();
buildMap();
memset(mapVisited,0,sizeof(mapVisited));
result=0;
mapVisited[0]=true;
solve(0,limit,0);
if(result)
printf("Case %d:\nThe best score is %d.\n",i,result);
else
printf("Case %d:\nImpossible\n",i);
if(i!=caseNum)
printf("\n");
}
}