加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

O(n)线性空间的迷宫生成算法

发布时间:2020-12-16 09:08:58 所属栏目:百科 来源:网络整理
导读:之前所有的迷宫生成算法,空间都是O(mn),时间同样是O(mn),时间上已经不可能更优化, 于是,我就从空间优化上着手,研究一个仅用O(n)空间的生成算法。 我初步的想法是,每次生成一行,生成后立即输出,而其连通性的信息用并查集保存。 然而这时却遇到阻力:

之前所有的迷宫生成算法,空间都是O(mn),时间同样是O(mn),时间上已经不可能更优化,

于是,我就从空间优化上着手,研究一个仅用O(n)空间的生成算法。

我初步的想法是,每次生成一行,生成后立即输出,而其连通性的信息用并查集保存。

然而这时却遇到阻力:不可能简单保存连通性信息就能完成。

因为通过上一行的信息去生成下一行的时候,仅靠连通性信息你无法知道你能不能结束当前路径上的连结,

也就是说你不能判断你能不能生成一个死胡同。

?

后来想了一下,改进了一下并查集,让它的父结点多保存一个信息:当前行与本结点连通的格子数

看这个例子:

 ━┳━━┳━━┳━━━━┳━━┳━━┳┓
┣┓┗━┃┃━━┛━━━┓┃┃┃┗┓┃┃┃
┃┗┳━┫┗━━┓┏━━┫┏┛┣━┃┃┃┃

?1 1??1 1 2 2 2 2 3?6?6?6 3 3 3 3 3 4 4 5

相同数字的表示它们连通(连向同一个父结点),比如3那个,当前行与本结点连通的格子数=6

也就是3出现的次数。

在生成下一行的时候,每生成一个格子,就得同时更新连通格子数的值,以保证不会生成环路和死路

参考源代码:

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

#define next(n,s) ((n)=(n)%((s)-1)+1)
int fset_size;
struct data
{
????int parent;
????int level;
????int sum;
}*fset;
int fset_pt = 1,fdeep;

int try_alloc(int level)
{
????if (fset[fset_pt].level < level)
????{
????????return fset_pt;
????}
????int lpt = fset_pt;
????for (next(fset_pt,fset_size); fset_pt!=lpt; next(fset_pt,fset_size))
????{
????????if (fset[fset_pt].level < level)
????????{
????????????return fset_pt;
????????}
????}
????return 0;
}

int reg_fset(int level)
{
????int lpt = fset_pt;
????fset[fset_pt].level = level;
????fset[fset_pt].parent = 0;
????fset[fset_pt].sum = 1;
????next(fset_pt,fset_size);
????return lpt;
}

int get_parent(int id)
{
????int d = id;
????for (fdeep=0; fset[id].parent>0; ++fdeep)
????????id = fset[id].parent;
????if (d != id) fset[d].parent = id;
????return id;
}

void insert(int a,int b)
{
????int pa = get_parent(a),da = fdeep;
????int pb = get_parent(b),db = fdeep;
????if (pa==pb)
????{
????}
????else if (da<=db)
????{
????????fset[pa].parent = pb;
????????fset[pb].level = max(fset[pa].level,fset[pb].level);
????????fset[pb].sum += fset[pa].sum-1;
????}
????else
????{
????????fset[pb].parent = pa;
????????fset[pa].level = max(fset[pa].level,fset[pb].level);
????????fset[pa].sum += fset[pb].sum-1;
????}
}

int is_connect(int a,int b)
{
????if (a==b || get_parent(a)==get_parent(b))
????????return 1;
????return 0;
}

struct tile
{
????int wall;
????int id;
};

char cw[][4]={" ","━","┃","┛","┗","┻","┓","┫","┏","┳","┣","╋"};

int Gen(int w,int h)
{
????int x,y,lx,ly,p;
????tile* maze = (tile*)malloc(sizeof(tile)*(w+2));
????fset = (data*)malloc(sizeof(data)*(w*2));
????fset_size = w;
????memset(fset,sizeof(data)*(w*2));
????for (x=0; x<=w+1; ++x) maze[x].wall = 7,maze[x].id=0;
????maze[0].wall = 15; maze[w+1].wall = 15;
????for (y=1; y<=h+1; ++y,maze[0].wall = 11,maze[w+1].wall = 14)
????{
????????lx = 0; ly = 1; x = 0;
????????fset[0].sum = 0;
????????p = 15;
????????if (lx) p &= ~8;
????????if (ly) p &= ~1;
????????if (maze[x+1].wall&8) p &= ~4;
????????if (is_connect(maze[x].id,maze[x+1].id)) p &= ~2;
????????if (y>h) p &= ~8;
????????printf(cw[p]);
????????p &= 4;
????????printf(cw[p]);
????????for (x=1; x<=w; ++x)
????????{
????????????int r,_r = 4;
????????????ly = (maze[x].wall&8);
????????????int id,dsum = 0;
????????????if (lx && ly)
????????????{
????????????????insert(maze[x-1].id,maze[x].id);
????????????}
????????????else if (lx==0 && ly==0)
????????????{
????????????????maze[x].id = try_alloc(y);
????????????????if (maze[x].id==0)
????????????????{
????????????????????fset_size += w;
????????????????????maze[x].id = try_alloc(y);
????????????????????fset_size -= w;
????????????????}
????????????????reg_fset(y+1);
????????????}
????????????else if (lx)
????????????{
????????????????maze[x].id = maze[x-1].id;
????????????}
????????????id = get_parent(maze[x].id);
????????????if ((maze[x+1].wall&8) && is_connect(maze[x].id,maze[x+1].id)) _r = 2;
????????????if (y==h && x==w)
????????????{
????????????????r = 0;
????????????}
????????????else do
????????????{
????????????????r = rand() % _r;
????????????????if ((r&2)==0 && try_alloc(y)==0) r |= 2;
????????????????if (y>h)
????????????????{
????????????????????r = 2;
????????????????}
????????????????else if (x==w) r &= ~2;
????????????????if (y==h) r &= ~1;
????????????????dsum = 0;
????????????????if ((r & 1) == 0 ) dsum -= 1;
????????????????if (r & 2) dsum += 1;
????????????}
????????????while (y<=h && ((r==0 && (lx==0 && ly==0) || fset[id].sum+dsum<=0 )) );
????????????maze[x].wall = 0;
????????????if (ly) maze[x].wall |= 2;
????????????if (lx)
????????????{
????????????????maze[x].wall |= 1;
????????????}
????????????lx = (r&2);
????????????if (lx) maze[x].wall |= 4;
????????????if (r&1) maze[x].wall |= 8;
????????????p = 15;
????????????if (maze[x].wall&4) fset[id].sum += 1;
????????????if ((maze[x].wall&8)==0) fset[id].sum -= 1,fset[0].sum += 1;
????????????fset[id].level = y+1;
????????????if (maze[x].wall&4) p &= ~8;
????????????if (maze[x].wall&2) p &= ~1;
????????????if (maze[x+1].wall&8) p &= ~4;
????????????if (maze[x+1].wall&1) p &= ~2;
????????????printf(cw[p]);
????????????p &= 4;
????????????printf(cw[p]);
????????}
????????puts("");
????????if (y<h)
????????{
????????????for (x=0; x<=w; ++x)
????????????{
????????????????if (maze[x].wall&4) printf(cw[0]); else printf(cw[10]);
????????????????int id = get_parent(maze[x].id);
????????????????maze[x].id = id;
????????????????printf(cw[0]);
????????????}
????????????puts("");
????????}
????????else if (y==h)
????????{
????????????for (x=0; x<=w; ++x)
????????????{
????????????????if ((maze[x].wall&4) || x==w) printf(cw[0]); else printf(cw[10]);
????????????????int id = get_parent(maze[x].id);
????????????????maze[x].id = id;
????????????????printf(cw[0]);
????????????}
????????????puts("");
????????}
????}
????free(maze);
????free(fset);
????return 0;
}
int main()
{
????srand((unsigned)time(NULL));
????Gen(15,10);
????return 0;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读