hdu 1044 Collect More Jewels 搜索
//hdu 1044 Collect More Jewels //搜索 //题意:起点 '@' 终点 '<' 宝石 'A' ~ 'J',在一定时间内 //从起点到终点,且求出能得到最多价值是多少 //思路:先用广搜求出起点、终点即所有宝石之间的最短距离 //然后深搜 #include <stdio.h> #include <string.h> #define N 55 #define INF 1<<30 #define eps 1e-5 const int dir[2][4] = {0, -1, 0, 1, -1, 0, 1, 0}; struct NODE { int x, y; }node[20], que[N*N]; int col, row, limit, n_jewel, ans; int jewel[15], step[N][N]; //step记录广搜中到某个结点的步数 int dis[20][20]; char map[N][N]; bool vis[20]; bool no_overmap(int x, int y) { return (x >= 0 && x < col && y >= 0 && y < row); } int get_index(int x, int y) { if(map[x][y] == '@') return n_jewel + 1; else if(map[x][y] == '<') return n_jewel; else return map[x][y] - 'A'; } void bfs(int root) //breadth first search { for(int i = 0; i < col; ++i) for(int j = 0; j < row; ++j) step[i][j] = 0; int head = 0, tail = 0; que[++head].x = node[root].x; que[head].y = node[root].y; while(tail < head) { int x = que[++tail].x, y = que[tail].y; for(int i = 0; i < 4; ++i) { int nx = x + dir[0][i], ny = y + dir[1][i]; if(no_overmap(nx, ny) && step[nx][ny] == 0 && map[nx][ny] != '*' && (nx != node[root].x || ny != node[root].y)) { step[nx][ny] = step[x][y] + 1; if(map[nx][ny] != '.') { int to = get_index(nx, ny); dis[root][to] = step[nx][ny]; } que[++head].x = nx; que[head].y = ny; } } } } void dfs(int root, int val, int time) { //记得判断当前点即root到终点的时间,否则超时,有的话也要900多毫秒才过 if(time + dis[root][n_jewel] > limit) return; if(root == n_jewel) { ans = ans > val ? ans : val; return; } //由于最短路之前都求过了,dfs只要判断该点要或不要就可以了 //则列举这些点的排列肯定有一种是答案,当前点可以要或不要 for(int i = 0; i <= n_jewel; ++i) { if(vis[i] == false && time + dis[root][i] <= limit) { vis[i] = true; dfs(i, val + jewel[i], time + dis[root][i]); vis[i] = false; } } } int main() { freopen("in.txt", "r", stdin); int n_case; scanf("%d", &n_case); for(int ca = 1; ca <= n_case; ++ca) { printf("Case %d:\n", ca); scanf("%d%d%d%d", &row, &col, &limit, &n_jewel); for(int i = 0; i < n_jewel; ++i) scanf("%d", &jewel[i]); for(int i = 0; i < col; ++i) { getchar(); for(int j = 0; j < row; ++j) { map[i][j] = getchar(); if(map[i][j] == '@') { node[n_jewel + 1].x = i; node[n_jewel + 1].y = j; jewel[n_jewel + 1] = 0; } if(map[i][j] == '<') { node[n_jewel].x = i; node[n_jewel].y = j; jewel[n_jewel] = 0; } if(map[i][j] >= 'A' && map[i][j] <= 'J') { node[map[i][j] - 'A'].x = i; node[map[i][j] - 'A'].y = j; } } } for(int i = 0; i <= n_jewel + 1; ++i) for(int j = 0; j < i; ++j) dis[i][j] = dis[j][i] = INF; bfs(n_jewel + 1); if(dis[n_jewel + 1][n_jewel] > limit) { printf("Impossible\n\n"); continue; } for(int i = 0; i <= n_jewel; ++i) //求i到各点的最短距离 bfs(i); for(int i = 0; i <= n_jewel + 1; ++i) vis[i] = false; ans = 0; dfs(n_jewel + 1, 0, 0); printf("The best score is %d.\n", ans); if(ca != n_case) puts(""); } return 0; }