转载请注明出处:優YoU http://user.qzone.qq.com/289065406/blog/1299324104

在一个y行 x列的迷宫中,有可行走的通路空格’ ‘,不可行走的墙’#’,还有两种英文字母A和S,现在从S出发,要求用最短的路径L连接所有字母,输出这条路径L的总长度。

一格的长度为1,而且移动的方法只有上、下、左、右,

所以在无任何墙的情况下(但“墙#”是必须考虑的,这里只是为了说明)

任意两个字母之间的距离就是直接把 横坐标之差 加上 纵坐标之差

注意的是,可行的路为 字母 和 空格

      不可行的路为 # 和 矩阵范围之外

根据题意的“分离”规则,重复走过的路不再计算

因此当使用prim算法求L的长度时,根据算法的特征恰好不用考虑这个问题(源点合并很好地解决了这个问题),L就是最少生成树的总权值W

由于使用prim算法求在最小生成树,因此无论哪个点做起点都是一样的,(通常选取第一个点),因此起点不是S也没有关系

所以所有的A和S都可以一视同仁,看成一模一样的顶点就可以了

最后要注意的就是 字符的输入

cin不读入空字符(包括 空格,换行等)

gets读入空格,但不读入换行符)

剩下的问题关键就是处理 任意两字母间的最短距离,由于存在了“墙#” ,这个距离不可能单纯地利用坐标加减去计算,必须额外考虑,推荐用BFS(广搜、宽搜),这是本题的唯一难点,因为prim根本直接套用就可以了

求 任意两字母间的最短距离 时不能直接用BFS求,

1、必须先把矩阵中每一个允许通行的格看做一个结点(就是在矩阵内所有非#的格都作为图M的一个顶点),对每一个结点i,分别用BFS求出它到其他所有结点的权值(包括其本身,为0),构造结点图M;

2、然后再加一个判断条件,从图M中抽取以字母为顶点的图,进而构造字母图N

这个判定条件就是当结点图M中的某点j为字母时,把i到j的权值再复制(不是抽离)出来,记录到字母图N的邻接矩阵中

3、剩下的就是对字母图N求最小生成树了

#include<stdio.h>
#include<iostream>
#include<cstdio>
#include<queue>
#include <vector>
#include<stack>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<climits>
#include<algorithm>
using namespace std;
#define ll unsinged long long
#define PI acos(-1.0)
#define ING 0x7fffffff
#define mod 1000000007
#define INF 3000 int dx[4]= {0,0,-1,1};
int dy[4]= {1,-1,0,0};
int node[105][105];
char ma[110][110]; int edge[110][110];
int num;
int n,m;
int que_x[1010],que_y[1010];
int vis[1010][1010]; void bfs(int i,int j)
{
int head,rail;
int dis[110][110]; head=rail=0;
memset(vis,0,sizeof(vis));
memset(dis,0,sizeof(dis)); que_x[rail]=i;
que_y[rail]=j;
rail++;
vis[i][j]=1; while(head<rail)
{
int x=que_x[head];
int y=que_y[head];
head++;
if(node[x][y])
edge[node[i][j]][node[x][y]]=dis[x][y]; for(int i=0; i<4; i++)
{
int mx=x+dx[i];
int my=y+dy[i];
if(mx<1||my<1||mx>m||my>n||vis[mx][my])
continue;
if(ma[mx][my]=='#')
continue;
vis[mx][my]=1;
dis[mx][my]=dis[x][y]+1;
que_x[rail]=mx;
que_y[rail]=my;
rail++;
}
}
} void prim()
{
// for(int i=1; i<=m; i++)
// {
// for(int j=1; j<=n; j++)
// {
// printf("%d ",edge[i][j]);
// }
// printf("\n");
// }
int mimi;
int d[110];
int v[110];
memset(v,0,sizeof(v));
for(int i=2; i<=num; i++)
{
d[i]=edge[1][i];
}
v[1]=1;
d[1]=0;
for(int i=1; i<=num-1; i++)
{
mimi=INF;
int k=0;
for(int j=1; j<=num; j++)
{
if(!v[j]&&d[j]<mimi)
{
k=j;
mimi=d[j];
}
}
v[k]=1;
for(int j=1; j<=num; j++)
{
if(!v[j]&&edge[k][j]<d[j])
d[j]=edge[k][j];
}
}
int ans=0;
for(int i=1; i<=num; i++)
{
ans+=d[i];
}
printf("%d\n",ans);
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
char s[51];
gets(s);
for(int i=1; i<=m; i++)
{
gets(ma[i]+1);
}
num=0;
memset(node,0,sizeof(node));
for(int i=1; i<=m; i++)
{
for(int j=1; j<=n; j++)
{
if(ma[i][j]=='A'||ma[i][j]=='S')
{
node[i][j]=++num;
}
}
}
// for(int i=1; i<=m; i++)
// {
// for(int j=1; j<=n; j++)
// {
// printf("%c",ma[i][j]);
// }
// printf("\n");
// }
for(int i=1; i<=m; i++)
{
for(int j=1; j<=n; j++)
{
if(node[i][j])
bfs(i,j);
}
}
prim();
}
return 0;
} //0 6 6 2 0 0
//6 0 2 4 0 0
//6 2 0 4 0 0
//2 4 4 0 0 0
//0 0 0 0 0 0
//
//0 1 2 5 3 4 5
//1 0 1 4 2 5 4
//2 1 0 3 3 6 5
//5 4 3 0 4 7 6
//3 2 3 4 0 3 2
//4 5 6 7 3 0 1
//5 4 5 6 2 1 0

BFS+PRIM的更多相关文章

  1. POJ 3026(BFS+prim)

    http://poj.org/problem?id=3026 题意:任意两个字母可以连线,求把所有字母串联起来和最小. 很明显这就是一个最小生成树,不过这个题有毒.他的输入有问题.在输入m和N后面,可 ...

  2. poj 3026 bfs+prim Borg Maze

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9718   Accepted: 3263 Description The B ...

  3. poj3026(bfs+prim)

    The Borg is an immensely powerful race of enhanced humanoids from the delta quadrant of the galaxy. ...

  4. POJ 3026 : Borg Maze(BFS + Prim)

    http://poj.org/problem?id=3026 Borg Maze Time Limit: 1000MS   Memory Limit: 65536K Total Submissions ...

  5. poj 3026 Borg Maze (BFS + Prim)

    http://poj.org/problem?id=3026 Borg Maze Time Limit:1000MS     Memory Limit:65536KB     64bit IO For ...

  6. Borg Maze(bfs+prim)

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6971   Accepted: 2345 Description The B ...

  7. J - Borg Maze - poj 3026(BFS+prim)

    在一个迷宫里面需要把一些字母.也就是 ‘A’ 和 ‘B’连接起来,求出来最短的连接方式需要多长,也就是最小生成树,地图需要预处理一下,用BFS先求出来两点间的最短距离, *************** ...

  8. POJ3026(BFS + prim)

    Borg Maze Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10554   Accepted: 3501 Descri ...

  9. 快速切题 poj 3026 Borg Maze 最小生成树+bfs prim算法 难度:0

    Borg Maze Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8905   Accepted: 2969 Descrip ...

  10. poj3026(bfs+prim)最小生成树

    The Borg is an immensely powerful race of enhanced humanoids from the delta quadrant of the galaxy. ...

随机推荐

  1. PAT 1003 Sharing (25)

    题目描写叙述 To store English words, one method is to use linked lists and store a word letter by letter. ...

  2. Js学习第十天----函数

    函数 什么是函数?函数是由事件驱动的或者当他被调用时运行的可反复使用代码块.预计没明确,个人觉得函数就是能完毕一个功能的代码块. 看个案例: <!DOCTYPE html> <htm ...

  3. linux下ndk编译命令行程序及配置

    1.在http://developer.android.com/tools/sdk/ndk/index.html下载Android-ndk-r8e-linux-x86.tar.bz2,解压后把andr ...

  4. 关于从 coding 拉项目的操作

    介绍:coding是托管代码的仓库   sourceTree 是把代码提交到coding的界面化工具 1.通过百度 登录coding账号

  5. java之static变量与全局、局部变量的区别

    static变量与全局.局部变量的区别 全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量.全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式.这两者在存储方式上并无 ...

  6. 【转载】究竟啥才是互联网架构“高并发”

    一.什么是高并发 高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求. 高并发相关常用的一些指标有响应时间( ...

  7. C#串口通讯教程 简化一切 只保留核心功能 这可能是最易于理解的一篇教程

    C#串口通讯教程 简化一切 只保留核心功能 这可能是最易于理解的一篇教程   串口的定义,请自行了解. C#操作串口通讯在.Net强大类库的支持下,只需要三个步骤: 1 创建 2 打开 3 发送/接受 ...

  8. Python常用的包

    Python常用的处理数据的包和它的Tutorial(点击每个包的名称): Numpy:提供对多维数组的支持,支持矢量运算,速度快 matplotlib.pyplot:图表的绘制 Pandas:基于 ...

  9. (转载)display:inline、block、inline-block的区别

    display:block就是将元素显示为块级元素. block元素的特点是: 总是在新行上开始: 高度,行高以及顶和底边距都可控制: 宽度缺省是它的容器的100%,除非设定一个宽度 <div& ...

  10. Asp.net常用的51个代码(非常实用)

    1.//弹出对话框.点击转向指定页面 Response.Write("<script>window.alert('该会员没有提交申请,请重新提交!')</script> ...