题目要求:Borg扫描到所有外星人的最低代价。
题目输入:输入x,y值,空格表示可以通过的空间,’#’表示有障碍物,不能通过,’A’表示外星人,’S’表示搜索的开始。
答题思路:先根据输入的矩阵建立出来一个无向图。’A’或者’S’表示一个顶点。使用广度优先算法找到每个顶点的邻节点。根据所建立图,利用prim求出最小生成树。
代码:
#include<stdio.h> #include<iostream> #include<queue> #include<string.h> #include<vector> using namespace std; #define MAX 10000 struct Point { int no;//他是第几个人,为了方便后面建立图 int x; int y; int time;//表示此结点需要几步可以被搜索到, }; struct Point location[50][50]; char str[50][50]; int **line; void BFS(struct Point p,int X,int Y)//搜索找到节点之间的相互距离 { bool visited[50][50]; memset(visited,0,sizeof(visited)); visited[p.x][p.y]=true;//表示这个节点是否被搜索 queue<Point> q; struct Point p1,p2; q.push(p); while(!q.empty()) { p1=q.front(); q.pop(); if(p1.x-1>=0&&!visited[p1.x-1][p1.y]) { visited[p1.x-1][p1.y]=true; if(str[p1.x-1][p1.y]==’A’||str[p1.x-1][p1.y]==’S’) { int id=location[p1.x-1][p1.y].no; if(line[p.no][id]>p1.time+1) { line[p.no][id]=p1.time+1; line[id][p.no]=p1.time+1; } } else if(str[p1.x-1][p1.y]==’ ‘) { p2.x=p1.x-1; p2.y=p1.y; p2.no=-1; p2.time=p1.time+1; q.push(p2); } } if(p1.x+1<X&&!visited[p1.x+1][p1.y]) { visited[p1.x+1][p1.y]=true; if(str[p1.x+1][p1.y]==’A’||str[p1.x+1][p1.y]==’S’) { int id=location[p1.x+1][p1.y].no; if(line[p.no][id]>p1.time+1) { line[p.no][id]=p1.time+1; line[id][p.no]=p1.time+1; } } else if(str[p1.x+1][p1.y]==’ ‘) { p2.x=p1.x+1; p2.y=p1.y; p2.no=-1; p2.time=p1.time+1; q.push(p2); } } if(p1.y-1>=0&&!visited[p1.x][p1.y-1]) { visited[p1.x][p1.y-1]=true; if(str[p1.x][p1.y-1]==’A’||str[p1.x][p1.y-1]==’S’) { int id=location[p1.x][p1.y-1].no; if(line[p.no][id]>p1.time+1) { line[p.no][id]=p1.time+1; line[id][p.no]=p1.time+1; } } else if(str[p1.x][p1.y-1]==’ ‘) { p2.x=p1.x; p2.y=p1.y-1; p2.no=-1; p2.time=p1.time+1; q.push(p2); } } if(p1.y+1<Y&&!visited[p1.x][p1.y+1]) { visited[p1.x][p1.y+1]=true; if(str[p1.x][p1.y+1]==’A’||str[p1.x][p1.y+1]==’S’) { int id=location[p1.x][p1.y+1].no; if(line[p.no][id]>p1.time+1) { line[p.no][id]=p1.time+1; line[id][p.no]=p1.time+1; } } else if(str[p1.x][p1.y+1]==’ ‘) { p2.x=p1.x; p2.y=p1.y+1; p2.no=-1; p2.time=p1.time+1; q.push(p2); } } } } int prim(int n)//求最小生成树 { vector<int> unvisited; unvisited.reserve(102); vector<int>::iterator iter=unvisited.begin(); vector<int> visited; visited.reserve(102); int i,j,id; visited.push_back(0); for(i=1;i<n;i++) unvisited.push_back(i); int cn=0,sum=0,min; while(++cn<n) { min=MAX; for(i=0;i<visited.size();i++)//分别在加入了最小生成树中的结点集合和未加入生成树的结点结合中找一个顶点 for(j=0;j<unvisited.size();j++) if(min>line[visited[i]][unvisited[j]]) { min=line[visited[i]][unvisited[j]]; id=j; } int x=unvisited[id]; unvisited.erase(iter+id); visited.push_back(x); sum+=min; } return sum; } int main() { int times; scanf(“%d”,×); while(times–) { int X,Y; int i,j; struct Point point; scanf(“%d%d/n”,&Y,&X); for(i=0;i<X;i++) gets(str[i]); //初始化location,如果是’A’or’S’,则是需要结点,标号count,否则标号-1(不是建立图的结点) int count=0; for(i=0;i<X;i++) for(j=0;j<Y;j++) { if(str[i][j]==’A’||str[i][j]==’S’) { point.no=count; point.time=0; point.x=i; point.y=j; count++; } if(str[i][j]==’ ‘) { point.no=-1; point.time=0; point.x=i; point.y=j; } if(str[i][j]==’#’) { point.no=-1; point.time=-1; point.x=i; point.y=j; } location[i][j]=point; } line=new int* [count]; for(i=0;i<count;i++) line[i]=new int[count]; for(i=0;i<count;i++) for(j=0;j<count;j++) line[i][j]=MAX; for(i=0;i<X;i++)//对于每个人进行搜索,看他能达到其他人的距离 for(j=0;j<Y;j++) if(str[i][j]==’A’||str[i][j]==’S’) BFS(location[i][j],X,Y); int ans=prim(count); printf(“%d/n”,ans); } return 0; }