->题目请戳这里<-
题目大意:迷宫问题。在一个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