码迷,mamicode.com
首页 > 其他好文 > 详细

随机漫步(random walk)

时间:2015-08-09 15:41:40      阅读:130      评论:0      收藏:0      [点我收藏+]

标签:随机漫步   random walk   random   模拟   

1、题目

有一类问题总称为“随机漫步”(Random Walk)问题,这类问题长久以来吸引着数学界的兴趣。所有这些问题即使是最简单的解决起来也是极其困难的。而且它们在很大程度上还远没有得到解决。一个这样的问题可以描述为:

在矩形的房间里,铺有n×m块瓷砖,现将一只(醉酒的)蟑螂放在地板中间一个指定方格里。蟑螂随机地从一块瓷砖“漫步”到另一块瓷砖(可能是在找一片阿司匹林)。假设它可能从其所在的瓷砖移动到其周围八块瓷砖中的任何一个(除非碰到墙壁),那么它把每一块瓷砖都至少接触一次将花费多长时间?

虽然这个问题可能很难用纯粹的概率技术来解决,但是使用计算机的话却十分容易。使用计算机解决此问题的技术称为“模拟”。这种技术广泛应用于工业中,用来预测运输流量,存货控制等等。该问题可以采用如下方式进行模拟:

用一个n×m的数组作为计数器来表示蟑螂到达每一块瓷砖的次数,每个数组单元的初始化均置为零。蟑螂在地板上的位置用坐标(currentR,currentC)表示。蟑螂的八种可能移动用在位置(NextR = currentR + imove[k],NextC = currentC + jmove[k])的瓷砖表示,其中0≤k≤7,并且

imove[0] = -1; jmove[0] = 1;   //东北方
imove[1] = 0; jmove[1] = 1;   //正东方
imove[2] = 1; jmove[2] = 1;   //东南方
imove[3] = 1; jmove[3] = 0;   //正南方
imove[4] = 1; jmove[4] = -1;  //西南方
imove[5] = 0; jmove[5] = -1;  //正西方
imove[6] = -1; jmove[6] = -1;  //西北方
imove[7] = -1; jmove[7] = 1;   //正北方

蟑螂向其相邻的八个方格的随机漫步通过产生一个随机数值k(0≤k≤7)来模拟。当然,蟑螂不能爬出房间外,所以应该去掉通往墙壁的坐标并形成一个新的随机组合。蟑螂每次进入一个方格,该方格的计数器就增加1,从而计数器的一个非零元素就表示蟑螂到达对应方格的次数。每当一个方格被至少进入一次时,试验就完成了。

2、条件

程序必须满足:

①能够处理所有的n和m值, n和m满足:2<n≤40,2≤m≤20;

②能够对“n = 15,m = 15,起始点为(10,10)”和“n = 39,m = 19,起始点为(1,1)”进行实验。

③具有迭代限制,即实验过程中蟑螂进入方块的最大次数为MAX =50000时,程序能够终止。

3、输出

对于每次试验,打印:

①蟑螂进行的合法移动的总次数。

②最终的计数器数组,显示出漫步的“密度”,即输出在实验中每一块瓷砖被接经过的次数。

4、源程序

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


int const MAX_LENGTH = 100;
int Random(int m,int n) //指定范围内随机数
{
    int pos,dis;
    if(m == n)  //表示范围内只有一个数字
        return m;
    else if(m > n)  //表示取区间[m,n]内的数字
    {
        pos = n;
        dis = m - n + 1;
        return rand() % dis + pos;
    }
    else    //表示取区间[n,m]内的数字
    {
        pos = m;
        dis = n - m + 1;
        return rand() % dis + pos;
    }
}


int rmove[8],cmove[8];  //移动方位数组
void InitMove(int* imove,int* jmove)    //初始化移动方位数组
{
    imove[0] = -1;
    jmove[0] = 1;   //东北方

    imove[1] = 0;
    jmove[1] = 1;   //正东方

    imove[2] = 1;
    jmove[2] = 1;   //东南方

    imove[3] = 1;
    jmove[3] = 0;   //正南方

    imove[4] = 1;
    jmove[4] = -1;  //西南方

    imove[5] = 0;
    jmove[5] = -1;  //正西方

    imove[6] = -1;
    jmove[6] = -1;  //西北方

    imove[7] = -1;
    jmove[7] = 1;   //正北方
}

bool judgewalk(int* mark[],int n,int m) //判断是否访问完所有瓷砖
{
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < m; j++)
        {
            if(!mark[i][j]) //如果有一个没访问完的瓷砖,则退出
                return false;
        }
    }
    return true;
}

void printwalk(int* mark[],int n,int m) //打印所有瓷砖访问次数
{
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < m; j++)
        {
            cout << mark[i][j] << " ";
        }
        cout << endl;
    }
}
void randomwalk(int** mark,int n,int m)  //随机漫步
{
    srand((int)time(NULL)); //根据时间产生相应种子值
    InitMove(rmove,cmove);  //初始化移动方位数组
    int currentR = Random(0,n - 1); //现在所在行
    int currentC = Random(0,m - 1); //现在所在列
    mark[currentR][currentC]++;
    int NextR,NextC;    //下一位置所在行,下一位置所在列
    int num = 0;        //移动次数
    while(true)
    {
        int moving = Random(0,7);   //随机产生移动方向
        NextR = currentR + rmove[moving];   //下一位置所在行
        NextC = currentC + cmove[moving];   //下一位置所在列
        while(NextR < 0 || NextC < 0 || NextR >=n || NextC >= m)   //当碰到墙壁时
        {
            moving = Random(0,7);   //随机产生移动方向
            NextR = currentR + rmove[moving];   //下一位置所在行
            NextC = currentC + cmove[moving];   //下一位置所在列
        }
        mark[NextR][NextC]++;   //访问+1
        currentR = NextR;
        currentC = NextC;   //下一位置等于当前位置
        num++;
        if(judgewalk(mark,n,m)) //判断是否访问完所有瓷砖
        {
            cout << "Total move step:" << num << endl;  //打印总步数
            printwalk(mark,n,m);    //打印所有瓷砖访问次数
            return;
        }
        if(num > 50000000) //超出访问上限次数
        {
            cout << "Cockroach don't visit all Tile." << endl;
            cout << "Total move step:" << num << endl;  //打印总步数
            printwalk(mark,n,m);
            return;
        }

    }
}

int main()
{
    int *mark[MAX_LENGTH];  //指针数组
    for(int i = 0; i < MAX_LENGTH; i++) //动态分配
        mark[i] = new int[MAX_LENGTH];
    for(int i = 0; i < MAX_LENGTH; i++) //初始化
        for(int j = 0; j < MAX_LENGTH;j++)
            mark[i][j] = 0;
    int n,m;  //行列
    cin >> n >> m;
    randomwalk(mark,n,m);
    for(int i = 0; i < MAX_LENGTH; i++) //释放空间
        delete[] mark[i];
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

随机漫步(random walk)

标签:随机漫步   random walk   random   模拟   

原文地址:http://blog.csdn.net/q547550831/article/details/47375497

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!