Borg Maze POJ - 3026 (bfs + prime)

題目鏈接

題意:一個 n * m 的圖中,’#’ 不能走之外,其他的地方都可以走,然後圖中散佈着 ‘S’ 和 ‘A’ ;問從 ‘S’ 出發到其餘的所有頂點最少需要多少步(到達任何的’A’之後可以同時向各個方向同時繼續出發到其他’A’點)

思路:既然可以從各個點出發,那麼其實就是把每個點兩兩之間的距離求出來,然後就是一個單純的求最小生成樹的問題了,那麼求距離就用bfs搜索就可以了。題目輸入有個坑點,題目的輸入會造成很多空格,所以在輸入之前需要清理一下。字符串中有空格需要注意一下就沒什麼大問題了;

bfs也不能亂來,之前我寫一種bfs寫法,就是每求完兩個點之間的距離之後都重新調用一次bfs,頻繁初始化vis數組導致超時,應該是一個點到剩下每個點的距離一次bfs就好了。

#include <iostream>
#include <queue>
using namespace std;

const int N = 505, M = N*N;
int _, n, m, dis[N][N], mp[N][N], num;
char s[N][N];
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};

struct point {
	int x, y, step;
	point(int x, int y, int step): x(x), y(y), step(step) {}
};

void bfs(int stax, int stay, int stanum) {
	bool vis[N][N]; memset(vis, 0, sizeof(vis));
	queue <point> q; while(!q.empty()) q.pop();
	q.push(point(stax, stay, 0));
	vis[stax][stay] = 1;
	while(!q.empty()) {
		point head = q.front(); q.pop();
		
		for(int i = 0;i < 4; i++) {
			int tx = head.x + dx[i];
			int ty = head.y + dy[i];
			if(!vis[tx][ty] && tx >= 0 && tx < m && ty >= 1 && ty <= n && mp[tx][ty] != -1) {
				if(mp[tx][ty]) {
					dis[stanum][mp[tx][ty]] = dis[mp[tx][ty]][stanum] = head.step+1;
				}
				vis[tx][ty] = 1;
				q.push(point(tx, ty, head.step+1));
			}
		}
	}
}

int prim() {
	bool isin[M];
	int lowcost[M], clostst[M];
	isin[1] = 1;
	for(int i = 1;i <= num; i++) {
		if(i != 1) {
			lowcost[i] = dis[1][i];
			clostst[i] = 1;
			isin[i] = 0;
		}
		else lowcost[i] = 0;
	}
	
	for(int i = 1;i <= num; i++) {
		int temp = 10000000;
		int t = 1;
		for(int j = 1;j <= num; j++) {
			if(!(isin[j]) && (lowcost[j] < temp)) {
				t = j;
				temp = lowcost[j];
			}
		}
		
		if(t == 1) break;
		isin[t] = 1;
		for(int j = 1;j <= num; j++) {
			if(!(isin[j]) && (dis[t][j] < lowcost[j])) {
				lowcost[j] = dis[t][j];
				clostst[j] = t;
			}
		}
	}

	int ans = 0;
	for(int i = 1;i <= num; i++) ans += lowcost[i];
	return ans;
}

int main() {
	scanf("%d", &_);
	while(_--) {
		scanf("%d %d", &m, &n);
		gets(s[0]);
		queue <point> qu; while(!qu.empty()) qu.pop();
		num = 1;
		for(int i = 1;i <= n; i++) gets(s[i]);
		for(int i = 1;i <= n; i++) {
			for(int j = 0;j < m; j++) {
				if(s[i][j] == 'S') mp[i][j] = 1;
				else if(s[i][j] == 'A') mp[i][j] = ++num;
				else if(s[i][j] == '#') mp[i][j] = -1;
				else mp[i][j] = 0;
				if(mp[i][j] > 0) {
					qu.push(point(i, j, mp[i][j]));
//					cout << "i = " << i << " j = " << j << " mp[i][j] = " << mp[i][j] << endl;
				}
			}
		}
//		cout << "qu.size = " << qu.size() << endl;
		while(!qu.empty()) {
			point t = qu.front(); qu.pop();
			bfs(t.x, t.y, t.step);
		}
		printf("%d\n", prim());
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章