您的位置:首页 > 编程语言 > Go语言

POJ 3026 Borg Maze (Prim Algorithm)

2016-03-18 11:05 447 查看
题目链接:

POJ 3026 Borg Maze

题意:

有一个n行*m列的字符矩阵,A代表一个需要同化的点,S代表起始点,#代表障碍,不可通过,‘ ’空格是可行的。

从s开始需要同化所有的A,并且一个A被同化后也具有了同化其他A的能力。输入保证S可到达任意一个A。

问从s开始同化所有的A需要多少步?

分析:

将所有的A和S看成一个个点,也就是求将这些点连通的最小生成树。

然后问题就是任意两点间的权值,并且这个权值是两点间所有可达路径中的最短路径。

对每一个点用一次BFS就好了,再用Prim Algorithm就行了。

注意:

n,m后面可能不止一个空格,太坑了……

//840K 110MS
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;

const int maxn=150;
const int INF=0x3f3f3f3f;

int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};//上下左右四个方向

int T,n,len,tot;
int cost[maxn][maxn],vis[maxn][maxn],dis[maxn],vvis[maxn];
char map[maxn][maxn],s[maxn];

struct Point{
int x,y;
}point[maxn];

struct Node{
int x,y,step;
}cur,nextnode;

void bfs(int u,int sr,int sc)//u,sr,sc分别是点编号和点所在行列
{
queue<Node> q;
cur.x=sr;
cur.y=sc;
cur.step=0;
memset(vis,0,sizeof(vis));//标记图上各点访问情况
vis[cur.x][cur.y]=1;
cost[u][u]=0;
q.push(cur);
while(!q.empty())
{
cur=q.front();
q.pop();
for(int i=0;i<4;i++)
{
int x=cur.x+dir[i][0];
int y=cur.y+dir[i][1];
if(x<0||y<0||x>=n||y>=len||vis[x][y]||map[x][y]=='#') continue;
//printf("%d %d\n",x,y);
nextnode.x=x;
nextnode.y=y;
nextnode.step=cur.step+1;
vis[x][y]=1;
for(int j=0;j<tot;j++)
{//因为图上每个可访问点都只访问一次,所以访问到一个点就是两点间的距离
if(point[j].x==x&&point[j].y==y)
{
cost[u][j]=nextnode.step;
}
}
q.push(nextnode);
}
}
}

int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
scanf("%d",&T);
while(T--)
{
tot=1;
scanf("%d%d",&len,&n);
for(int i=0;i<n;i++)
{
gets(s);//一开始这里写getchar();结果WA了,看Discuss才知道原来后台数据len,n后面还有空格
for(int j=0;j<len;j++)
{
scanf("%c",&map[i][j]);
if(map[i][j]=='A')
{
point[tot].x=i;
point[tot].y=j;
tot++;
}
else if(map[i][j]=='S')//起点下标为0
{
point[0].x=i;
point[0].y=j;
}
}
}
/*
for(int i=0;i<n;i++)
{
for(int j=0;j<len;j++)
{
putchar(map[i][j]);
}
printf("\n");
}
*/
for(int i=0;i<tot;i++)//对每一点求相应边长,由于起点可到达任意一点,那么任意两点间都是连通的
bfs(i,point[i].x,point[i].y);

/*
for(int i=0;i<tot;i++)
{
for(int j=0;j<tot;j++)
{
printf("%d ",cost[i][j]);
}
printf("\n");
}
*/

//Prim Algorithm
memset(vvis,0,sizeof(vvis));
vvis[0]=1;
int ans=0;
for(int i=0;i<tot;i++)//一共有tot个点
dis[i]=cost[0][i];
for(int i=1;i<tot;i++)
{
int k=-1;
int tmp=INF;
for(int j=0;j<tot;j++)
{
if(!vvis[j]&&dis[j]<tmp)
{
k=j;
tmp=dis[j];
}
}
vvis[k]=1;
ans+=tmp;
for(int j=0;j<tot;j++)
{
if(!vvis[j]&&dis[j]>cost[k][j]) dis[j]=cost[k][j];
}
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  prim