
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