题目链接:Collect More Jewels
解题思路:一看又是简单的广搜,还以为水题,所以简单敲了一发,T了。思佳说用BFS + DFS。算了算总状态数50*50*2^10 = 256W, 一共10组,而且还有它给出的时间有可能很多,这样所有宝物都能捡到还能瞎逛。就是宝物逝去序列的所有组合。所以应该先处理两两宝物之间的最短路,和起点到所有宝物的最短路,终点到所有宝物的最短路,全部用BFS跑一遍,然后再对所有宝物进行DFS找到最大的价值,要注意如果已经找到最大值就要直接退出,否则会TLE。减枝很重要。
#include<cstdio> #include<cstring> #include<queue> #define MAX 55 #define MAXN 20 #define INF 0x5f5f5f5f using namespace std; struct node{ int x, y, s; node(){} node(int xx, int yy, int ss){ x = xx, y = yy, s = ss; } }; int n, m, l, k; int g[MAX][MAX], dis[MAXN][MAXN]; bool v[MAX][MAX], vis[MAXN]; int jv[MAXN], jx[MAXN], jy[MAXN]; int ans, sx, sy, ex, ey, sum; int dir[4][2] = {1,0,-1,0,0,1,0,-1}; void init(){ for(int i = 0; i < k; i++){ for(int j = 0; j < k; j++){ dis[i][j] = i == j ? 0 : INF; } } ans = -1; memset(vis, 0, sizeof(vis)); } int getC(char c){ if(c == '@') return 0; if(c == '<') return k - 1; if(c >= 'A' && c <= 'J') return c - 'A' + 1; return -1; } void bfs(int x, int y, int idx){ int i, j; queue<node> mq; memset(v, false, sizeof(v)); v[x][y] = true; mq.push(node(x, y, 0)); while(!mq.empty()){ node s = mq.front(); //printf("idx = %d %d %d %d\n", idx, s.x, s.y, s.s); mq.pop(); for(i = 0; i < 4; i++){ int xx = s.x + dir[i][0]; int yy = s.y + dir[i][1]; int ss = s.s + 1; if(xx >= 0 && xx < n && yy >= 0 && yy < m && !v[xx][yy] && g[xx][yy] != '*'){ v[xx][yy] = true; if(getC(g[xx][yy]) != -1){ dis[getC(g[xx][yy])][idx] = ss; dis[idx][getC(g[xx][yy])] = ss; } mq.push(node(xx, yy, ss)); } } } } void dfs(int now, int d, int v, int pre){ //printf("%d %d %d %d\n",pre, now, d, v); int i, j; if(d > l || sum == ans) return; if(now == k - 1 && v > ans){ ans = v; } for(i = 0; i < k; i++){ if(dis[now][i] == INF || vis[i]) continue; vis[i] = true; dfs(i, d + dis[now][i], v + jv[i], now); vis[i] = false; } } int main(){ int i, j, t, tot = 0; //#ifndef ONLINE_JUDGE //freopen("1.in", "r", stdin); //freopen("1.out", "w", stdout); //#endif // ONLINE_JUDGE scanf("%d", &t); while(t--){ if(tot++) printf("\n"); scanf("%d%d%d%d", &m, &n, &l, &k); sum = 0; for(i = 1; i <= k; i++){ scanf("%d", &jv[i]); sum += jv[i]; } jv[0] = jv[k + 1] = 0; k += 2; init(); for(i = 0; i < n; i++){ getchar(); for(j = 0; j < m; j++){ g[i][j] = getchar(); if(g[i][j] == '@'){ jx[0] = i, jy[0] = j; } if(g[i][j] == '<'){ jx[k - 1] = i, jy[k - 1] = j; } if(g[i][j] <= 'J' && g[i][j] >= 'A'){ jx[g[i][j] + 1 - 'A'] = i; jy[g[i][j] + 1 - 'A'] = j; } } } for(i = 0; i < k - 1; i++){ bfs(jx[i], jy[i], i); } printf("Case %d:\n", tot); if(dis[0][k - 1] > l){ puts("Impossible"); continue; } vis[0] = true; dfs(0, 0, 0, -1); if(ans == -1){ puts("Impossible"); } else{ printf("The best score is %d.\n", ans); } } return 0; }