是否有算法随机填充这样的矩阵?

时间:2017-04-26 09:19:27

标签: algorithm matrix graph nodes

考虑r行大小和c列大小的矩阵 给定例如r = 19和c = 11,我们将得到具有209个元素的矩阵。所有元素的赋值都为0.所以我们有一个包含0&#39的大矩阵。

鉴于以下6"区域" Area1:31个元素 Area2:35个元素 区域3:35个元素 Area4:37个元素 Area5:32个元素 Area6:39个元素

总结所有面积元素加起来209,这样它们就可以填满整个矩阵。

是否有算法用每个区域填充矩阵并将元素的值设置为区域名称? 我需要的实际上不是设置部分,而只是找到元素及其附近的算法部分。

矩阵区域应该看起来像......让我们在世界地图上说国家/地区。所以我们不能拥有" area1"矩阵左边的元素,然后是右边的元素,它们之间有其他区域。这些区域应该是浓缩的,具有随机的形状"在接管矩阵元素时形成。

基本上,为了让它更容易理解,我想象它就像在给定大小的地图上创建给定大小的随机区域(209)。

任何人,您可以建议的任何现有算法?或任何方法?

编辑:填充整个空间的6个区域(基于给定的示例)。不应该留下任何背景元素(0个值元素)。我们示例中的6个区域应完全填充209个元素。

1 个答案:

答案 0 :(得分:1)

为了保持一些随机性我像这样解决这个问题:

  1. 生成每个种子的种子起点

    简单地计算每个区域的随机起始点,约束条件是任何2个起点必须至少在彼此之间具有一定的最小距离。这将为增长提供一些空间,因此结果看起来更好。

  2. 尽可能种植每粒种子

    只是迭代地扩大每个区域,直到没有间隙存在(忽略所需的区域大小)

  3. 更正尺寸

    因此,只需占领区域i=1并将其从任何相邻区域j>i放大/缩小。然后处理i=2 ...完成后按降序执行相同操作,然后从任何邻居i=n获取区域j<i并放大/缩小。

    循环这整个事情,直到地区的大小正确

  4. 验证

    bullet #3 可以将某些地区划分为非后果区域,我怀疑这是不受欢迎的。所以检测一下,如果案例再次产生这一切。

    要为每个区域检测到这个,请找到它的第一个有效单元格和泛洪填充 算一下这个领土有多大。如果不匹配区域的大小,则应再次生成。

    如果所有地区都与尺码相匹配,那么地图就是相关的,您就完成了

  5. 此处预览#1,#2,#3:

    preview

    表单标题中的数字是地区actual size - wanted size第一个数字是间隔,然后是领土1,2,3 ...

    我的C ++实现:

    //---------------------------------------------------------------------------
    // generator properties
    const int n=7;          // teritories+1
    const int mx=19;        // map size
    const int my=11;
    const int siz[n]={ 0,31,35,35,37,32,39 };   // teritory sizes (first is bordrer)
    const int mindist=5;    // min distance between teritory seed points
          int map[mx][my];  // map 0 means no teritory else it is teritory ID
    // rendering properties
    const int grid=16;      // grid size [pixels]
    const DWORD col[n]=     // teritory color table
        {
        0x00000000,         // border (unused)
        0x00FF0000,         // territory 1
        0x0000FF00,         // territory 2
        0x000000FF,         // territory 3
        0x00FFFF00,         // territory 4
        0x0000FFFF,         // territory 5
        0x00FF00FF,         // territory 6
        };
    //---------------------------------------------------------------------------
    void map_generate()
        {
        int x,y,xx,yy,i,j,e;
        int cnt[n];     // generated teritory size
        int seedx[n];   // start position for teritory
        int seedy[n];
    
    //  AnsiString s="";
    //  s+=AnsiString().sprintf("Seed: %X |",RandSeed);
    
        for (;;)
            {
            // clear map
            cnt[0]=mx*my;
            for (x=0;x<mx;x++)
             for (y=0;y<my;y++)
              map[x][y]=0;
            // start position
            for (i=1;i<n;)
                {
                // ranom position
                seedx[i]=Random(mx);
                seedy[i]=Random(my);
                // find closest seed point x = distance to it
                for (x=mx+my,j=1;j<i;j++)
                    {
                    y=abs(seedx[i]-seedx[j])+abs(seedy[i]-seedy[j]);
                    if (x>y) x=y;
                    }
                // if OK use as seed point else repeat the whole thing again...
                if (x>mindist)
                    {
                    map[seedx[i]][seedy[i]]=i;
                    cnt[i]=1; cnt[0]--; i++;
                    }
                }
    
            // un bounded growth fill (can exceeding area)
            for (e=1;e;)
                {
                e=0;
                for (x=   1;x<mx;x++) for (y=0;y<my;y++) { i=map[x][y]; if (i>0){ x--; if (map[x][y]==0) { map[x][y]=i; cnt[i]++; cnt[0]--; e=1; } x++; }}
                for (x=mx-2;x>=0;x--) for (y=0;y<my;y++) { i=map[x][y]; if (i>0){ x++; if (map[x][y]==0) { map[x][y]=i; cnt[i]++; cnt[0]--; e=1; } x--; }}
                for (x=0;x<mx;x++) for (y=   1;y<my;y++) { i=map[x][y]; if (i>0){ y--; if (map[x][y]==0) { map[x][y]=i; cnt[i]++; cnt[0]--; e=1; } y++; }}
                for (x=0;x<mx;x++) for (y=my-2;y>=0;y--) { i=map[x][y]; if (i>0){ y++; if (map[x][y]==0) { map[x][y]=i; cnt[i]++; cnt[0]--; e=1; } y--; }}
                }
    
            // correct inequalities cnt[] vs. siz[]
            for (;;)
                {
                // stop if all counts are matching
                for (i=1;i<n;i++) if (cnt[i]!=siz[i]) { i=-1; break; } if (i>=0) break;
                // growth i from any neighbor j>i
                for (i=1;i<n;i++)
                 for (e=1;(e)&&(cnt[i]<siz[i]);)
                    {
                    e=0;
                    for (x=   1;x<mx;x++) for (y=0;y<my;y++) if ((i==map[x][y])&&(cnt[i]<siz[i])){ x--; j=map[x][y]; if ((i<j)&&(cnt[j]>1)){ map[x][y]=i; cnt[i]++; cnt[j]--; e=1; } x++; }
                    for (x=mx-2;x>=0;x--) for (y=0;y<my;y++) if ((i==map[x][y])&&(cnt[i]<siz[i])){ x++; j=map[x][y]; if ((i<j)&&(cnt[j]>1)){ map[x][y]=i; cnt[i]++; cnt[j]--; e=1; } x--; }
                    for (x=0;x<mx;x++) for (y=   1;y<my;y++) if ((i==map[x][y])&&(cnt[i]<siz[i])){ y--; j=map[x][y]; if ((i<j)&&(cnt[j]>1)){ map[x][y]=i; cnt[i]++; cnt[j]--; e=1; } y++; }
                    for (x=0;x<mx;x++) for (y=my-2;y>=0;y--) if ((i==map[x][y])&&(cnt[i]<siz[i])){ y++; j=map[x][y]; if ((i<j)&&(cnt[j]>1)){ map[x][y]=i; cnt[i]++; cnt[j]--; e=1; } y--; }
                    }
                // shrink i from any neighbor j>i
                for (i=1;i<n;i++)
                 for (e=1;(e)&&(cnt[i]>siz[i]);)
                    {
                    e=0;
                    for (x=   1;x<mx;x++) for (y=0;y<my;y++) if ((i==map[x][y])&&(cnt[i]>siz[i])){ x--; j=map[x][y]; if (i<j)              { map[x+1][y]=j; cnt[j]++; cnt[i]--; e=1; } x++; }
                    for (x=mx-2;x>=0;x--) for (y=0;y<my;y++) if ((i==map[x][y])&&(cnt[i]>siz[i])){ x++; j=map[x][y]; if (i<j)              { map[x-1][y]=j; cnt[j]++; cnt[i]--; e=1; } x--; }
                    for (x=0;x<mx;x++) for (y=   1;y<my;y++) if ((i==map[x][y])&&(cnt[i]>siz[i])){ y--; j=map[x][y]; if (i<j)              { map[x][y+1]=j; cnt[j]++; cnt[i]--; e=1; } y++; }
                    for (x=0;x<mx;x++) for (y=my-2;y>=0;y--) if ((i==map[x][y])&&(cnt[i]>siz[i])){ y++; j=map[x][y]; if (i<j)              { map[x][y-1]=j; cnt[j]++; cnt[i]--; e=1; } y--; }
                    }
    
                // stop if all counts are matching
                for (i=1;i<n;i++) if (cnt[i]!=siz[i]) { i=-1; break; } if (i>=0) break;
                // growth i from any neighbor j<i
                for (i=n-1;i>0;i--)
                 for (e=1;(e)&&(cnt[i]<siz[i]);)
                    {
                    e=0;
                    for (x=   1;x<mx;x++) for (y=0;y<my;y++) if ((i==map[x][y])&&(cnt[i]<siz[i])){ x--; j=map[x][y]; if ((i>j)&&(cnt[j]>1)){ map[x][y]=i; cnt[i]++; cnt[j]--; e=1; } x++; }
                    for (x=mx-2;x>=0;x--) for (y=0;y<my;y++) if ((i==map[x][y])&&(cnt[i]<siz[i])){ x++; j=map[x][y]; if ((i>j)&&(cnt[j]>1)){ map[x][y]=i; cnt[i]++; cnt[j]--; e=1; } x--; }
                    for (x=0;x<mx;x++) for (y=   1;y<my;y++) if ((i==map[x][y])&&(cnt[i]<siz[i])){ y--; j=map[x][y]; if ((i>j)&&(cnt[j]>1)){ map[x][y]=i; cnt[i]++; cnt[j]--; e=1; } y++; }
                    for (x=0;x<mx;x++) for (y=my-2;y>=0;y--) if ((i==map[x][y])&&(cnt[i]<siz[i])){ y++; j=map[x][y]; if ((i>j)&&(cnt[j]>1)){ map[x][y]=i; cnt[i]++; cnt[j]--; e=1; } y--; }
                    }
                // shrink i from any neighbor j<i
                for (i=n-1;i>0;i--)
                 for (e=1;(e)&&(cnt[i]>siz[i]);)
                    {
                    e=0;
                    for (x=   1;x<mx;x++) for (y=0;y<my;y++) if ((i==map[x][y])&&(cnt[i]>siz[i])){ x--; j=map[x][y]; if (i>j)              { map[x+1][y]=j; cnt[j]++; cnt[i]--; e=1; } x++; }
                    for (x=mx-2;x>=0;x--) for (y=0;y<my;y++) if ((i==map[x][y])&&(cnt[i]>siz[i])){ x++; j=map[x][y]; if (i>j)              { map[x-1][y]=j; cnt[j]++; cnt[i]--; e=1; } x--; }
                    for (x=0;x<mx;x++) for (y=   1;y<my;y++) if ((i==map[x][y])&&(cnt[i]>siz[i])){ y--; j=map[x][y]; if (i>j)              { map[x][y+1]=j; cnt[j]++; cnt[i]--; e=1; } y++; }
                    for (x=0;x<mx;x++) for (y=my-2;y>=0;y--) if ((i==map[x][y])&&(cnt[i]>siz[i])){ y++; j=map[x][y]; if (i>j)              { map[x][y-1]=j; cnt[j]++; cnt[i]--; e=1; } y--; }
                    }
                }
            // test if teritories are not divided and regenerate if needed
            for (xx=0,i=1;i<n;i++)
                {
                // clear temp bit
                for (x=0;x<mx;x++)
                 for (y=0;y<my;y++)
                  map[x][y]&=65535;
                // find first occurence
                j=0;
                for (x=0;x<mx;x++)
                 for (y=0;y<my;y++)
                  if (map[x][y]==i) { map[x][y]|=65536; j=1; x=mx; y=my; }
                if (!j) { xx=1; break; }        // teritory not found
                // growth fill count into j
                for (e=1;e;)
                 for (e=0,x=0;x<mx;x++)
                  for (   y=0;y<my;y++)
                   if (map[x][y]==i)
                    {
                    yy=0;
                    if ((x>   0)&&(map[x-1][y]>=65536)) yy=1;
                    if ((x<mx-1)&&(map[x+1][y]>=65536)) yy=1;
                    if ((y>   0)&&(map[x][y-1]>=65536)) yy=1;
                    if ((y<my-1)&&(map[x][y+1]>=65536)) yy=1;
                    if (yy){ j++; map[x][y]|=65536; e=1; }
                    }
                if (j!=siz[i]) { xx=1; break; } // teritory incorrect size
                }
            if (xx) continue;                   // regenerate again
            // clear temp bit
            for (x=0;x<mx;x++)
             for (y=0;y<my;y++)
              map[x][y]&=65535;
            break;                              // al OK so stop
            }
    
    //  for (i=0;i<n;i++) { s+=cnt[i]-siz[i]; s+=" "; }
    //  Main->Caption=s;
        }
    //---------------------------------------------------------------------------
    

    代码没有经过优化,以保持它尽可能简单易懂...(可以重新编码得快得多)。