2 3 ##@ #.# 1 2 2 4 4 #@## .... #### .... 2 2 1 2 4 0 0
-1 5
#include <cstdio> #include <cstring> #include <queue> #include <string> #include <algorithm> #include <iostream> using namespace std; int const MAX = 100 + 5; int map[MAX][MAX]; int n, m, k, cnt; int dx[] = {1, 0, -1, 0}; int dy[] = {0, 1, 0, -1}; char s[105]; struct Point //存点的信息 { int x, y; int step; int id; }p[105]; int ex, ey; int dis[105][105]; bool vis[105][105]; void BFS(Point pt, Point ept) { vis[pt.x][pt.y] = true; Point now, t; queue <Point> q; q.push(pt); while(!q.empty()) { now = q.front(); q.pop(); if(now.x == ex && now.y == ey) //记录两点间的最短路 { dis[pt.id][ept.id] = now.step; dis[ept.id][pt.id] = now.step; return; } for(int i = 0; i < 4; i ++) { t = now; t.x += dx[i]; t.y += dy[i]; t.step ++; if(t.x >= n || t.x < 0 || t.y >= m || t.y < 0 || vis[t.x][t.y] || map[t.x][t.y] == 0) continue; vis[t.x][t.y] = true; q.push(t); } } } int main() { while(scanf("%d %d", &n, &m) && (n + m)) { bool f = false; int ans = 0; string next; char tmp[10]; cnt = 0; memset(map, 0, sizeof(map)); memset(dis, -1, sizeof(dis)); for(int i = 0; i < n; i++) { scanf("%s", s); for(int j = 0; j < m; j++) { if(s[j] == '.') map[i][j] = 1; if(s[j] == '@') { map[i][j] = 3; p[cnt].x = i; p[cnt].y = j; p[cnt].id = cnt; p[cnt++].step = 0; } } } int bx, by; scanf("%d", &k); for(int i = 0; i < k; i++) { scanf("%d %d", &bx, &by); if(map[bx - 1][by - 1] == 0) f = true; else map[bx - 1][by - 1] = 2; } for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) if(map[i][j] == 2) { p[cnt].x = i; p[cnt].y = j; p[cnt].id = cnt; p[cnt++].step = 0; } //将起点设置为0点方便后面的操作 for(int i = 0; i < cnt; i++) //枚举任两点并搜其最短路径 { for(int j = i + 1; j < cnt; j++) { ex = p[j].x; ey = p[j].y; memset(vis, false, sizeof(vis)); BFS(p[i],p[j]); } } for(int i = 0; i < cnt; i++) //如果存在宝藏不可达则说明无解 { for(int j = 0; j < cnt; j++) { if(i == j) continue; if(dis[i][j] == -1) { f = true; break; } } if(f) break; } if(f) { printf("-1\n"); continue; } //计算每种情况下的总路程 for(int i = 0; i < cnt - 1; i++) tmp[i] = i + 49; next.insert(0,tmp,0,cnt-1); int cur = 0; for(int i = 0; i < cnt - 1; i++) { ans += dis[cur][next[i] - 48]; cur = next[i] - 48; } while(next_permutation(next.begin(), next.end())) //举出所有排列 { int re = 0; cur = 0; for(int i = 0; i < cnt - 1; i++) { re += dis[cur][next[i] - 48]; cur = next[i] - 48; } ans = min(ans, re); } printf("%d\n", ans); } }
HDU 4771 Stealing Harry Potter's Precious (生成排列+枚举 + BFS)
原文地址:http://blog.csdn.net/tc_to_top/article/details/43699133