Borg Maze POJ - 3026 BFS+最小生成树

传送门

题目大意: 地图上A代表外星人, 从S出发, 吃掉所有外星人, 每吃掉外星人都可以分裂成多个(在S也可以分裂成多个)。 求最少走多少步可以吃掉所有外星人。

题目分析: 从题目可以看出S和A是等价的,把A直接认为是S即可。 问题可以转化为把所有A(S已经转化为A了)连起来需要走多少步。 最小生成树问题。 还有第二个问题就是如何求两个点之间的权重。 用bfs求两个点之间的最小距离即可。 每个点都进行一次bfs即可求得所有点对之间的最小距离。

注意: 这个题的测试样例有个很蛋疼的地方, 就是给你长宽两个数字之后, 不不仅仅是一个回车, 当时我用getchar() 读的地图, 然后用getchar()吃掉数字后面的回车符, 结果WA了···当时就懵了, 看了一遍代码实在找不出来, 就看了题解, 基本上都跟我一个思路啊,为啥我的不对, 结果看到有个题解说用getchar会wa, 然后我就试了试gets, 高版本中gets不让用, 就自己写了个gets。 就A了, 多试了几次发现, 可能是后面的数据用程序生成的, 生成的时候没有处理两个数字后面的空格。

代码:

#include <iostream>
#include <cstdio>
#include <queue>

using namespace std;
typedef pair<int, int> P;
const int INF = 1 << 31 -1;
char mp[55][55];
int n, m;
int ID[55][55];
int V;
int dx[] = {0,0,-1,1}, dy[] = {1,-1,0,0};
int cost[2505][2505];


void bfs(int x, int y)
{
	queue<P> que;
	int cnt[55][55] = {0};
	mp[x][y] = '#';
	cost[ID[x][y]][ID[x][y]] = 0;
	for(que.push(P(x, y)); !que.empty(); que.pop())
	{
		P p = que.front();
		int xx = p.first;
		int yy = p.second;
		if(mp[xx][yy] == 'A')
			cost[ID[x][y]][ID[xx][yy]] = min(cost[ID[x][y]][ID[xx][yy]], cnt[xx][yy]);

		for(int i=0; i<4; ++i)
		{
			xx = p.first + dx[i];
			yy = p.second + dy[i];
			if(xx < n && yy < m && xx >= 0 && yy >= 0 && !cnt[xx][yy] && mp[xx][yy] != '#')
			{
				que.push(P(xx, yy));
				cnt[xx][yy] = cnt[p.first][p.second] + 1;
			}
		}
	}
	mp[x][y] = 'A';
}

int mincost[2505];
int used[2505];

int Prim()
{
	int ans = 0;
	for(int i=0; i<V; ++i)
	{
		mincost[i] = INF;
		used[i] = false;
	}
	mincost[0] = 0;

	while(1)
	{
		int v = -1;
		for(int i=0; i<V; ++i)
			if(!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;
		if(v == -1) break;
		ans += mincost[v];
		used[v] = true;

		for(int i=0; i<V; ++i)
			mincost[i] = min(mincost[i], cost[v][i]);
	}
	return ans;
}

void readline(char * s)   //自制gets
{
	char ch = getchar();
	int i = 0;
	while(ch != '\n')
	{
		s[i++] = ch;
		ch = getchar();
	}
	s[i] = 0;
}

int main()
{
	int T;
	scanf("%d", &T);
	while(T--)
	{
		V = 0;
		scanf("%d%d", &m, &n);
		readline(mp[0]);     //吃掉多余的换行
		for(int i=0; i<n; ++i)
		{
			readline(mp[i]);
			for(int j=0; j<m; ++j)
			{
				if(mp[i][j] == 'A') ID[i][j] = V++;
				else if(mp[i][j] == 'S')
				{
					ID[i][j] = V++;
					mp[i][j] = 'A';
				}
			}
		}
		for(int i=0; i<V; ++i) fill(cost[i], cost[i]+V, INF);

		for(int i=0; i<n; ++i)
			for(int j=0; j<m; ++j)
				if(mp[i][j] == 'A') bfs(i, j);
		printf("%d\n", Prim());
	}

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值