【J - Borg Maze】

80 篇文章 0 订阅
80 篇文章 0 订阅

思路:

  • 最小生成树+BFS
  • 自己想出来哒,但是数据好坑,输入长宽后有一大堆空格,WA 的好难受。感谢CMyDreamer的BLOG
  • 题目很麻烦,依次需要读图,存图,BFS 枚举每两个点之间的最短路径,Prim 求以 S 为根的最小生成树。还用到了两种结构体两个优先队列,分别用于 BFSPrim
  • 可以使用 map 优化查找。我没有写。

代码:

  • 63ms 792kB
//63ms		792kB 


#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#define INF 0x3f3f3f3f

using namespace std;

const int maxn = 105;
int N,M;
int ans;
int dis[maxn];
bool vis[maxn];//PRIM 
bool book[maxn][maxn];//BFS
char mp[maxn][maxn];//存图 
const int mt[4][2] = {1,0 , 0,1 , -1,0 , 0,-1} ;//moveto
int W[maxn][maxn];//存储点点距 
struct ORD{
	int x;
	int y;
}ord[maxn];int cnt;//from 1..cnt
struct NODE{
	int id;
	int dis;
	friend bool operator > (NODE a , NODE b)
	{
		return a.dis > b.dis;
	}
	NODE(int id,int dis) : id(id) , dis(dis) {} ; 
};
priority_queue <NODE , vector<NODE> , greater<NODE> > Q;//用于PRIM 
struct GRID{ 
	int x,y;
	int step;//可用map优化。
	friend bool operator > (GRID a,GRID b)
	{
		return a.step > b.step; 
	} 
	GRID(int x,int y,int step) : x(x) , y(y) , step(step) {} ;
};
priority_queue <GRID , vector<GRID> , greater<GRID> > q;//用于BFS 

void INIT(){
	ans = 0;
	cnt = 0;
	memset(W , 0 , sizeof(W));
	memset(vis , 0 , sizeof(vis));
	memset(dis , INF , sizeof(dis));
	return ;
}

bool check(int x,int y){
	if(x < 1 || x > M || y < 1 || y > N || mp[x][y] == '#')
		return false;
	return true;
}

void BFS(int s){
	memset(book , 0 , sizeof(book));
	q.push(GRID(ord[s].x , ord[s].y , 0));book[ord[s].x][ord[s].y] = true;
	while(q.size()){
		GRID cur = q.top() ; q.pop() ;
		int x = cur.x;
		int y = cur.y;
		if(mp[x][y] == 'A'){
			int i;
			for(i = 1;i <= cnt;i++)
				if(ord[i].x == x && ord[i].y == y)
					break;
			W[s][i] = W[i][s] = cur.step;
		}
		for(int i=0;i<4;i++){
			int nx = x + mt[i][0];
			int ny = y + mt[i][1];
			if(check(nx,ny) && !book[nx][ny]){
				book[nx][ny] = true;
				q.push(GRID(nx,ny,cur.step+1));
			}
		}
	}
	return ;
}

void PRIM(){
	dis[0] = 0;
	Q.push(NODE(0 , 0));
	while(Q.size()){
		NODE cur = Q.top() ; Q.pop() ;
		int id = cur.id;
		if(vis[id])
			continue;
		ans += dis[id];
		vis[id] = true;
		for(int i=1;i<=cnt;i++)
			if(!vis[i] && dis[i] > W[id][i]){
				dis[i] = W[id][i];
				Q.push(NODE(i , dis[i]));
			}
	}
	return ;
}

int main(){
	int T;cin>>T;
	while(T--){
		INIT();
		cin>>N>>M;
		char gar[maxn];
		gets(gar);//getchar()就会WA,有一大堆空格 
		for(int i=1;i<=M;i++){
			for(int j=1;j<=N;j++){
				char ch = mp[i][j] = getchar();
				if(ch == 'A'){
					++cnt;
					ord[cnt].x = i;
					ord[cnt].y = j;
				}
				if(ch == 'S'){
					ord[0].x = i;
					ord[0].y = j;
				}
			}
			getchar();
		}
		for(int i=0;i<=cnt;i++)
			BFS(i);
		PRIM();
		cout<<ans<<endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值