随机漫步(random walk)

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;
}

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

时间: 2024-10-11 12:11:15

随机漫步(random walk)的相关文章

醉汉随机行走/随机漫步问题(Random Walk Drunk Python)

世界上有些问题看似是随机的(stochastic),没有规律可循,但很可能是人类还未发现和掌握这类事件的规律,所以说它们是随机发生的. 随机漫步(Random  Walk)是一种解决随机问题的方法,它与人类生活息息相关,例如醉汉行走的轨迹.布朗运动(Brownian Motion).股票的涨跌等都可以用它来模拟.随机漫步已经应用到数学,物理,生物学,医学,经济等领域. 假设某地有一个醉汉,每一秒钟会朝"东","南","西","北&quo

【Python】随机漫步

创建Randomwalk()类 我们将使用Python来生成随机漫步数据,再使用matplotlib以引入瞩目的方式将这些数据呈现出来 首先创建类Randomwalk() from random import choice class RandomWalk(): '''一个生成随机漫步数据的类''' def __init__(self,num_points=5000): '''初始化随机漫步的属性''' self.num_points = num_points #所有的随机漫步都始于(0,0)

Python中的 matplotlib(二)随机漫步

创建一个随机漫步的类: 1 from random import choice 2 3 4 class RandomWalk(): 5 '''一个生成随机漫步数据的类''' 6 7 def __init__(self, num_points=5000): 8 '''初始化随机漫步的属性''' 9 self.num_points = num_points 10 '''所有的随机漫步都始于(0,0)''' 11 self.x_values = [0] 12 self.y_values = [0] 1

HDU 4487 Maximum Random Walk 概率 dp

D - Maximum Random Walk Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4487 Appoint description:  System Crawler  (2016-05-03) Description Consider the classic random walk: at each step, you ha

加入商品分类信息,考虑用户所处阶段的 图模型 推荐算法 Rws(random walk with stage)

场景: 一个新妈妈给刚出生的宝宝买用品,随着宝宝的长大,不同的阶段需要不同的物品. 这个场景中涉及到考虑用户所处阶段,给用户推荐物品的问题. 如果使用用户协同过滤,则需要根据购买记录,找到与用户处于同一阶段的用户. 不加入分类信息,单纯使用物品信息,则可能因为买了不同牌子的尿布,而判断为非相似用户, 所以加入商品分类信息 算法步骤: 1.   加入分类信息 1)   根据时间将用户交易记录分成若干阶段(比如,近90天,近360天-近90天,...) 2)   对于中的记录(以中的为例),在向量的

2013ACM-ICPC杭州赛区全国邀请赛——Random Walk

题目链接 题意: n个点,按照题中给的公式可以求出任意两个点转移的概率.求从1到n的期望转移次数 分析: 设dp[i]为从i到n的期望,那么可以得到公式dp[i] = sigma(dp[i + j] * p(i + j, i)),1 <= j <= m 把这个式子展开来:dp[i - m] * p(i - m, i) + dp[i - m + 1] * dp(i - m + 1, i) + ... + dp[i] * p(i, i) + ... + dp[i + m] * p(i + m, i

HDOJ 4579 Random Walk 解方程

Random Walk Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others) Total Submission(s): 200    Accepted Submission(s): 117 Problem Description Yuanfang is walking on a chain. The chain has n nodes numbered from 1 to n. Ev

HDU 4487 Maximum Random Walk

Maximum Random Walk Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 756    Accepted Submission(s): 419 三维dp,一维的话根本没有办法开展,二维的话没办法保存当前位置或者最远位置,所以只能用三维的. 看不懂滚动数组之类的操作,只能傻傻的写. 具体内容在代码里标注了,三重循环,从i,j,

随机游走模型(Random Walk)

给定了一个时间顺序向量\(z_1,...,z_T\),rw模型是由次序r来定义的,\(z_t\)仅取决于前\(t-r\)个元素.当r = 1时为最简单的RW模型. 给定了向量的其他元素,\(z_t\)的条件分布为: \(z_t|z_{t-1} ~ Normal(z_{t-1} ,\sigma^2)\) 原文地址:https://www.cnblogs.com/jiaxinwei/p/12304503.html