并查集的应用之一。
主要思路是:
将所有墙加入一个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");
}