题目大意:给出一个m×n的迷宫,迷宫中有若干(小于100)个外星人,现在Borg要同化这些外星人,Borg可以向上下左右移动,但不能碰撞到墙(即题中的“#”)。已知外星人(用“A”表示)和Borg(用“S”表示)所在位置的坐标,问你要同化所有外星人所需要的最短路线是多少。定义两点之间的距离为这两点纵坐标之差的绝对值加上这两点横坐标之差的绝对值。另外Borg可以同时向不同方向移动,此时他走的路程也是在这些方向上各自走过路程的加和。
分析:由于是要求出S点到所有A点的路径的最小和,很容易看出这是一个典型的最小生成树问题。那么问题来了,怎么去构建生成树所在的原图G?以及G中各边的权值怎么求?其实每条边的权值正是S到A的最短距离,我们先把S到每一个A点的最短距离找出来,作为G的权值,然后就可以直接找出G的最小生成树了。至于怎么找出S到某一个A点的最短距离呢?显而易见,BFS可以解决。我感觉本题的突破口就在于给每一个A和S点标号,作为图G中的顶点编号,这一步可是在输入的过程中纪录,我们用一个变量num表示G中的顶点个数,那么在遍历迷宫的过程中,每遇见一个A或者S,n都让num++即可。
实现代码如下:
#include <cstdio> #include <iostream> #include <queue> #include <cstring> using namespace std; typedef struct node { int x,y; }point; int mov[4][2]={{0,-1},{0,1},{-1,0},{1,0}};//方向数组 int n,m,num; char maze[55][55];//纪录迷宫 int pos[55][55];//纪录A和S的坐标的标号 int map[105][105];//最小生成树所在的原图G int dis[105][105];//纪录BFS过程中每个点到起始点的最小距离 void bfs(int x,int y) { bool s[55][55]; memset(s,false,sizeof(s)); memset(dis,0,sizeof(dis)); queue<point> que; point p,cnt,tmp; p.x=x; p.y=y; s[p.x][p.y]=true; que.push(p); while(!que.empty()) { cnt=que.front(); que.pop(); if(pos[cnt.x][cnt.y]) map[pos[x][y]][pos[cnt.x][cnt.y]]=dis[cnt.x][cnt.y]; for(int i=0;i<4;i++) { int cx=cnt.x+mov[i][0]; int cy=cnt.y+mov[i][1]; if(cx<=m&&cx>=1&&cy<=n&&cy>=1&&!s[cx][cy]&&maze[cx][cy]!='#') { s[cx][cy]=true; tmp.x=cx; tmp.y=cy; que.push(tmp); dis[cx][cy]=dis[cnt.x][cnt.y]+1; } } } return ; } int prime() { int w[105]; int sum=0; bool s[105]; for(int i=1;i<=num;i++) { w[i]=map[1][i]; s[i]=false; } s[1]=true; for(int i=1;i<=num;i++) { int tmp=2550; int u=1; for(int j=1;j<=num;j++) if(!s[j]&&tmp>w[j]) { tmp=w[j]; u=j; } s[u]=true; sum+=w[u]; for(int j=1;j<=num;j++) if(!s[j]&&w[j]>map[u][j]) w[j]=map[u][j]; } return sum; } void creat_G() { for(int i=1;i<=num;i++) for(int j=1;j<=num;j++) map[i][j]=2550; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(pos[i][j]) bfs(i,j); } int main() { int t; cin>>t; while(t--) { memset(pos,0,sizeof(pos)); num=0; scanf("%d%d",&m,&n); char a[5]; gets(a);//吃掉scanf后的回车 for(int i=1;i<=n;i++) { gets(maze[i]); for(int j=1;j<=m;j++) if(maze[i][j]=='A'||maze[i][j]=='S') pos[i][j]=++num; } creat_G(); cout<<prime()<<endl; } return 0; }