题目链接。
题目大意:
任意两点(点表示字母)可以连线,求使所有点连通,且权值和最小。
分析:
第一感觉使3维的BFS。但写着写着,发现不对。
应当用最小生成树解法。把每个字母(即A,或S)看成一个结点,如果求出来任意两个结点间的权值,则求解即为求最小生成树。
通过暴力,对每一个字母进行BFS,求出任意两个结点的距离。然后prim.
AC代码如下:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <queue> using namespace std; const int maxn = 52; const int INF = (1<<29); int dx[] = {0, 0, -1, 1}; int dy[] = {1, -1, 0, 0}; struct Pos { int x, y; }; char G[maxn][maxn]; //存放地图 bool vis[maxn][maxn]; //深搜时用的标记数组 int num[maxn][maxn], node[110][110]; //num表示字母编号(从0开始),node字母间的最短距离 int dis[maxn][maxn]; //深搜时用来记录到(sx,sy)的最短距离 int n, m, cn; void BFS(int sx, int sy) { queue<Pos> Q; memset(vis, 0, sizeof(vis)); Q.push((Pos){sx, sy}); vis[sx][sy] = true; dis[sx][sy] = 0; while(!Q.empty()) { Pos e = Q.front(); Q.pop(); int x = e.x, y = e.y; if(num[x][y] != -1) //(x,y)这点是字母 node[num[sx][sy]][num[x][y]] = dis[x][y]; for(int d=0; d<4; d++) { int nx = x+dx[d]; int ny = y+dy[d]; if(nx < 0 && ny < 0 && nx >= n && ny >= m) continue; if(vis[nx][ny] || G[nx][ny] == '#') continue; vis[nx][ny] = true; dis[nx][ny] = dis[x][y]+1; Q.push((Pos){nx, ny}); } } } int prim(int s) { /* * cn为结点数,node为邻接矩阵 * 任意两点间距离node[i][j] * 本题就是prim模板 */ int d[110], ans = 0; bool v[110]; memset(v, false, sizeof(v)); for(int i=0; i<cn; i++) { d[i] = node[s][i]; } v[s] = true; d[s] = 0; for(int i=0; i<cn-1; i++) { int x, m=INF; for(int y=0; y<cn; y++) if(!v[y] && m >= d[y]) m = d[x=y]; v[x] = true; ans += m; for(int y=0; y<cn; y++) if(!v[y] && d[y] > node[x][y]) d[y] = node[x][y]; } return ans; } int main() { int T, n, m, ns; char tmp[200]; scanf("%d", &T); while(T--) { scanf("%d%d", &m, &n); gets(tmp); //discuss上说后面有多个空格 for(int i=0; i<n; i++) { gets(G[i]); } cn = 0; //字母的个数 memset(num, -1, sizeof(num)); for(int i=0; i<n; i++) { for(int j=0; j<m; j++) { if(G[i][j] == 'S' || G[i][j] == 'A') { //对字母进行编号 num[i][j] = cn++; } if(G[i][j] == 'S') { //'S'的编号 ns = cn-1; } } } for(int i=0; i<n; i++) { for(int j=0; j<m; j++) { if(G[i][j] == 'A' || G[i][j] == 'S') BFS(i, j); } } printf("%d ", prim(ns)); } return 0; }