【问题标题】:Is there an algorithm to randomly fill a matrix like this?有没有一种算法可以随机填充这样的矩阵?
【发布时间】:2017-04-26 09:19:26
【问题描述】:

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

鉴于以下 6 个“领域” 区域 1:31 个元素 区域 2:35 个元素 区域 3:35 个元素 区域 4:37 个元素 区域 5:32 个元素 区域 6:39 个元素

所有区域元素的总和为 209,因此它们填充了整个矩阵。

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

矩阵区域应该看起来像......假设世界地图上的国家领土。所以我们不能在矩阵的左边有“area1”元素,然后在右边有其他区域。这些区域应该是压缩的,具有在接管矩阵元素时形成的随机“形状”。

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

任何人,您可以建议任何现有的算法吗?或者有什么办法?

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

【问题讨论】:

  • 就可以了。如果它有任何意义。我是在我的小屏幕手机上做的
  • 您没有正式定义形状/区域几何形状,并且在大多数情况下,这可能是一个类似于 NP 硬包装的问题。
  • 我没有定义形状,因为形状应该尽可能随机。而且我真的不知道如何做到这一点,也不知道是否有可能在没有定义任何形状的情况下实现真正的随机。
  • 对于n 区域——在空间的中心,从中心到周边绘制n-2 线,在中心的角度等距。然后画一个country 为一团,不管它在中心和周围占据多少空间。将国家 2 放入第一个扇区,以占据足够的空间,.... 顺时针围绕空间工作。现在告诉我们为什么这种简单、头脑简单的方法不能满足您的要求。
  • 我将尝试实施您的方法。听起来是个好主意@High Performance Mark

标签: algorithm matrix graph nodes


【解决方案1】:

为了保持一些随机性,我这样处理这个问题:

  1. 为每个区域生成种子起点

    只需计算每个区域的随机起点,其中任何两个起点之间必须至少有一些已定义的最小距离。这将提供一些增长空间,因此结果看起来更好。

  2. 尽可能地种植每一粒种子

    简单地迭代扩大每个区域,直到不存在间隙(忽略所需的区域大小)

  3. 更正尺寸

    所以只需将领土i=1 和任何邻近领土j>i 放大/缩小。然后处理i=2 ...完成后按降序执行相同的操作,因此占据i=n的领土并从任何邻居j<i放大/缩小。

    循环整个过程,直到区域大小正确

  4. 验证

    bullet #3 可以将一些区域划分为非后续区域,我怀疑这是不受欢迎的。所以检测到这一点,如果案件再次产生这整个事情。

    仅针对每个区域进行检测,找到它的第一个有效单元格并填充 算一算那块领地有多大。如果与已划分的区域大小不匹配,则应重新生成。

    如果所有地区都匹配大小,则地图是相关的,您就完成了

这里是#1,#2,#3的预览:

表格标题中的数字是领土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;
    }
//---------------------------------------------------------------------------

代码没有经过优化以使其尽可能简单易懂......(可以重新编码以更快)。

【讨论】:

  • 我正在尝试更多选项,包括您的。最终我会以不同的答案回来,或者接受你的正确答案。感谢您的所有努力,您确实提供了帮助,即使不是整个算法,至少也提供了一些深刻的见解和想法:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-22
  • 2020-08-19
相关资源
最近更新 更多