zoukankan      html  css  js  c++  java
  • 模拟沉积法

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

       

    首先初始化一个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>

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

  • 相关阅读:
    122. Best Time to Buy and Sell Stock II
    121. Best Time to Buy and Sell Stock
    72. Edit Distance
    583. Delete Operation for Two Strings
    582. Kill Process
    indexDB基本用法
    浏览器的渲染原理
    js实现txt/excel文件下载
    git 常用命令
    nginx进入 配置目录时
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5154109.html
Copyright © 2011-2022 走看看