• 模拟沉积法


    在一次随机化算法测试中我无意发现,通过粒子的随机移动和沉积可构造类似如下图形

       

    首先初始化一个N*N的网格,其中每个格子有几率p1被放置一个粒子,状态设为活跃,在中心放置一个非活跃粒子,

    随机选择一个活跃粒子和移动方向(上下左右),若粒子的这个方向上1格没有粒子或边界则移动,若粒子接触到非活跃粒子则有p2几率变为非活跃粒子(沉积),

    直到所有粒子变为非活跃状态,算法结束。

    通常p1取0.05~0.2,p2取0.5~1.0,也可以对不同的粒子设置不同的p1,p2

    加入重力等其它规则有时可以得到意想不到的效果

    测试表明此算法在p1=0.1,p2=1时期望时间复杂度大约是O(n4),然而我没有能力证明。

    以下是一个简单的实现

    c++版

    #include<cstdio>
    #include<cstdlib>
    #include<ctime>
    const int N=200;
    const double p1=0.1;
    const double p2=1.0;
    int xs[]={-1,0,1,0};
    int ys[]={0,-1,0,1};
    int bmp[N+2][N+2];
    struct pos{
        int x,y;
        pos(){}
        pos(int a,int b):x(a),y(b){}
    }ps[N*N];
    int p=0;
    int main(){
        srand(time(0));
        for(int i=0;i<=N+1;i++)//边界
            bmp[0][i]=bmp[N+1][i]=bmp[i][0]=bmp[i][N+1]=-1;
        for(int i=1;i<=N;i++)
            for(int j=1;j<=N;j++)
                if(rand()<RAND_MAX*p1){//初始化
                    bmp[i][j]=1;
                    ps[p++]=pos(i,j);
                }
        bmp[N/2+1][N/2+1]=2;
        while(p){
            int w=rand()%p;
            int x=ps[w].x,y=ps[w].y;
            int f=rand()&3;
            bool d=0;
            if(bmp[x][y]==2)d=1;
            else for(int i=0;i<4;i++)
                if(bmp[x+xs[i]][y+ys[i]]==2)
                    d=1;
            if(d&&rand()<p2*RAND_MAX){//沉积
                bmp[x][y]=2;
                ps[w]=ps[--p];
                continue;
            }
            if(bmp[x+xs[f]][y+ys[f]]==0){//移动
                bmp[ps[w].x=x+xs[f]][ps[w].y=y+ys[f]]=1;
                bmp[x][y]=0;
            }
        }
      //结果保存在数组bmp中
    return 0; }

    js+html5版,图形化界面

    <html>
    <body>
    <p>
    模拟沉积法生成器(测试版)
    <br/>
    需js及html5支持
    <br/>
    边长较大时可能需要较长时间 
    </p>
    <br/>
    边长(10~200) <input type="text" id="N" value="50"></input>
    <br/>
    p1(0.05~0.5) <input type="text" id="p1" value="0.12"></input>
    <br/>
    p2(0.5~1) <input type="text" id="p2" value="1"></input>
    <br/>
    <input type='button' onclick='onc()' value='生成'></input>
    <br/>
    <canvas id="canvas" width="400" height="400"></canvas>
    <script type="text/javascript">
    var cv=document.getElementById("canvas")
    var i1=document.getElementById("N")
    var i2=document.getElementById("p1")
    var i3=document.getElementById("p2")
    var ctx=cv.getContext('2d')
    var n=50;
    var vs=new Array()
    var ps=new Array()
    var xs=new Array()
    var ys=new Array()
    xs[0]=-1;xs[1]=0;xs[2]=1;xs[3]=0
    ys[0]=0;ys[1]=-1;ys[2]=0;ys[3]=1
    var p=0,p1=0.12,p2=1
    var doing=0
    function draw(x,y){
        ctx.fillRect(x*2,y*2,2,2)
    }
    function rnd(){
        return Math.random()
    }
    function pre(){
        ctx.fillStyle="white"
        ctx.fillRect(0,0,400,400)
        ctx.fillStyle="red"
        p=0
        for(var i=0;i<=n+1;i++)vs[i]=new Array(n+2)
        for(var i=1;i<=n;i++)
            for(var j=1;j<=n;j++)
                if(rnd()<p1){
                    vs[i][j]=1
                    ps[p++]={x:i,y:j}
                }else vs[i][j]=0
        for(var i=0;i<=n+1;i++)vs[i][0]=vs[i][n+1]=vs[0][i]=vs[n+1][i]=-1
        vs[n/2+1][n/2+1]=2
        draw(n/2+1,n/2+1)
    }
    function cal(){
    doing=1
    pre()
    while(p>0){
        var w=Math.floor(rnd()*p)
        var x=ps[w].x,y=ps[w].y
        var f=Math.floor(rnd()*4)
        var d=0
        if(vs[x][y]==2)d=1
        else for(var i=0;i<4;i++){
            if(vs[x+xs[i]][y+ys[i]]==2)d=1
        }
        if(d>0&&rnd()<p2){
            vs[x][y]=2
            ps[w]=ps[--p]
            draw(x,y)
        }else if(vs[x+xs[f]][y+ys[f]]==0){
            vs[x+xs[f]][y+ys[f]]=1
            vs[x][y]=0
            ps[w].x+=xs[f]
            ps[w].y+=ys[f]
        }
    }
    doing=0
    }
    function onc(){
        if(doing)return
        n=parseInt(i1.value)
        p1=parseFloat(i2.value)
        p2=parseFloat(i3.value)
        if(n<=200&&n>0&&p1>=0.05&&p1<=0.5&&p2>=0.5&&p2<=1)cal()
        else{
            i1.value=""
            i2.value=""
            i3.value=""
        }
    }
    cal()
    </script>
    </body>
    </html>

    暂时并没有什么实用价值。。

  • 相关阅读:
    Spring bean作用域
    软件类说明文档排版建议
    fit_line_contour_xld拟合直线的五种算法的准确度比较
    .Net优秀开源(5)SqlSugar
    .NET[C#]中实现实体对象深拷贝(克隆/复制)的几种方法
    spring框架学习(14)AOP(中)
    .Net优秀开源(4)Castle.Core
    .Net优秀开源(3)Dapper
    .Net优秀开源(2)Autofac
    .Net优秀开源(1)
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5154109.html
Copyright © 2020-2023  润新知