【并查集】一种迷宫生成算法

并查集的应用之一。

主要思路是:

将所有墙加入一个vector
while vector非空:
	在vector中随机选一个墙
	墙的两边是否联通?
		否: 联通墙的两边(打破墙)0
	删除本墙

代码:

#include<bits/stdc++.h>
#include<conio.h>
using namespace std;
int fa[10000],dx[2]={0,1},dy[2]={1,0},n=15,mp[21][21][21][21];
//n可修改 为迷宫大小 同时为防止溢出请修改fa和mp大小
int WtoN(int a,int b){
	return (a-1)*n+b;
}//将墙的(1,1)转为第1个的序号
int found(int f){
	if(fa[f]==f)return f;
	else return fa[f]=found(fa[f]);
}//并查集
struct wall{
	int fx,fy,sx,sy;
	void merge(){
		fa[found(WtoN(fx,fy))]=found(WtoN(sx,sy));
	}//让并查集好看一些 在struct里面写了一个
	bool check(){
		return found(WtoN(fx,fy))==found(WtoN(sx,sy));
	}
};
void print(){
	for(int i=1;i<=3*n+1;i++)cout<<"#";
	cout<<endl;
	for(int i=1;i<=n;i++){
		cout<<"#";
		for(int j=1;j<=n;j++)cout<<"  "<<(((j!=n)&&(mp[i][j][i][j+1]))?" ":"#");
		cout<<endl;
		for(int j=1;j<=n;j++)cout<<"#"<<(((i!=n)&&(mp[i][j][i+1][j]))?"  ":"##");
		cout<<"#"<<endl;
	}
}//输出 不多讲 mp[][][][]==1代表当前墙被打破了
int main(){
	srand((unsigned int)time(NULL));
	for(int i=1;i<=n*n;i++)fa[i]=i;
	vector<wall>vc;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			for(int d=0;d<2;d++){
				int rx=i+dx[d],ry=j+dy[d];
				if(rx>0&&ry>0&&rx<=n&&ry<=n)vc.push_back((wall){i,j,rx,ry});
			}
		}
	}//初始化墙列表
	while(!vc.empty()){
		int v=rand()%vc.size();//选择一面墙
		if(!vc[v].check())vc[v].merge(),mp[vc[v].fx][vc[v].fy][vc[v].sx][vc[v].sy]=1;//打破墙
		vc.erase(vc.begin()+v);//删除
	}
	print();
	system("pause");
}
posted @ 2021-03-03 18:35  Haraki  阅读(271)  评论(0编辑  收藏  举报