Expected number of moves to reach the end of a board | Matrix Exponentiation

Given a linear board of length N numbered from 1 to N, the task is to find the expected number of moves required to reach the Nth cell of the board, if we start at cell numbered 1 and at each step we roll a cubical dice to decide the next move. Also, we cannot go outside the bounds of the board. Note that the expected number of moves can be fractional.

Examples:

Input: N = 8
Output: 7
p1 = (1 / 6) | 1-step -> 6 moves expected to reach the end
p2 = (1 / 6) | 2-steps -> 6 moves expected to reach the end
p3 = (1 / 6) | 3-steps -> 6 moves expected to reach the end
p4 = (1 / 6) | 4-steps -> 6 moves expected to reach the end
p5 = (1 / 6) | 5-steps -> 6 moves expected to reach the end
p6 = (1 / 6) | 6-steps -> 6 moves expected to reach the end
If we are 7 steps away, then we can end up at 1, 2, 3, 4, 5, 6 steps
away with equal probability i.e. (1 / 6).
Look at the above simulation to understand better.
dp[N – 1] = dp[7]
= 1 + (dp[1] + dp[2] + dp[3] + dp[4] + dp[5] + dp[6]) / 6
= 1 + 6 = 7



Input: N = 10
Output: 7.36111

Approach: An approach based on dynamic programming has already been discussed in an earlier post. In this article, a more optimized method to solve this problem will be discussed. The idea is using a technique called Matrix-Exponentiation.

Let’s define An as the expected number of moves to reach the end of a board of length N + 1.
The recurrence relation will be:

An = 1 + (An-1 + An-2 + An-3 + An-4 + An-5 + An-6) / 6

Now, the recurrence relation needs to be converted in a suitable format.

An = 1 + (An-1 + An-2 + An-3 + An-4 + An-5 + An-6) / 6 (equation 1)
An-1 = 1 + (An-2 + An-3 + An-4 + An-5 + An-6 + An-7) / 6 (equation 2)
Substracting 1 with 2, we get An = 7 * (An-1) / 6 – (An-7) / 6

Matrix exponentiation technique can be applied here on the above recurrence relation.
Base will be {6, 6, 6, 6, 6, 6, 0} corresponding to {A6, A5, A4…, A0}
Multiplier will be

{
{7/6, 1, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0},
{0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0, 1, 0, 0},
{0, 0, 0, 0, 0, 1, 0},
{0, 0, 0, 0, 0, 0, 1},
{-1/6, 0, 0, 0, 0, 0, 0}
}

To find the value:

  • Find mul(N – 7)
  • Find base * mul(N – 7).
  • The first value of the 1 * 7 matrix will be the required answer.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the approach
#include <bits/stdc++.h>
#define maxSize 50
using namespace std;
  
// Function to multiply two 7 * 7 matrix
vector<vector<double> > matrix_product(
    vector<vector<double> > a,
    vector<vector<double> > b)
{
    vector<vector<double> > c(7);
    for (int i = 0; i < 7; i++)
        c[i].resize(7, 0);
  
    for (int i = 0; i < 7; i++)
        for (int j = 0; j < 7; j++)
            for (int k = 0; k < 7; k++)
                c[i][j] += a[i][k] * b[k][j];
    return c;
}
  
// Function to perform matrix exponentiation
vector<vector<double> > mul_expo(vector<vector<double> > mul, int p)
{
  
    // 7 * 7 identity matrix
    vector<vector<double> > s = { { 1, 0, 0, 0, 0, 0, 0 },
                                  { 0, 1, 0, 0, 0, 0, 0 },
                                  { 0, 0, 1, 0, 0, 0, 0 },
                                  { 0, 0, 0, 1, 0, 0, 0 },
                                  { 0, 0, 0, 0, 1, 0, 0 },
                                  { 0, 0, 0, 0, 0, 1, 0 },
                                  { 0, 0, 0, 0, 0, 0, 1 } };
  
    // Loop to find the power
    while (p != 1) {
        if (p % 2 == 1)
            s = matrix_product(s, mul);
        mul = matrix_product(mul, mul);
        p /= 2;
    }
  
    return matrix_product(mul, s);
}
  
// Function to return the required count
double expectedSteps(int x)
{
  
    // Base cases
    if (x == 0)
        return 0;
    if (x <= 6)
        return 6;
  
    // Multiplier matrix
    vector<vector<double> > mul = { { (double)7 / 6, 1, 0, 0, 0, 0, 0 },
                                    { 0, 0, 1, 0, 0, 0, 0 },
                                    { 0, 0, 0, 1, 0, 0, 0 },
                                    { 0, 0, 0, 0, 1, 0, 0 },
                                    { 0, 0, 0, 0, 0, 1, 0 },
                                    { 0, 0, 0, 0, 0, 0, 1 },
                                    { (double)-1 / 6, 0, 0, 0, 0, 0, 0 } };
  
    // Finding the required multiplier
    // i.e mul^(X-6)
    mul = mul_expo(mul, x - 6);
  
    // Final answer
    return (mul[0][0]
            + mul[1][0]
            + mul[2][0]
            + mul[3][0]
            + mul[4][0]
            + mul[5][0])
           * 6;
}
  
// Driver code
int main()
{
    int n = 10;
  
    cout << expectedSteps(n - 1);
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java implementation of the approach
class GFG
{
static final int maxSize = 50;
  
// Function to multiply two 7 * 7 matrix
static double [][] matrix_product(double [][] a,
                                  double [][] b)
{
    double [][] c = new double[7][7];
  
    for (int i = 0; i < 7; i++)
        for (int j = 0; j < 7; j++)
            for (int k = 0; k < 7; k++)
                c[i][j] += a[i][k] * b[k][j];
    return c;
}
  
// Function to perform matrix exponentiation
static double [][] mul_expo(double [][] mul, int p)
{
  
    // 7 * 7 identity matrix
    double [][] s = {{ 1, 0, 0, 0, 0, 0, 0 },
                     { 0, 1, 0, 0, 0, 0, 0 },
                     { 0, 0, 1, 0, 0, 0, 0 },
                     { 0, 0, 0, 1, 0, 0, 0 },
                     { 0, 0, 0, 0, 1, 0, 0 },
                     { 0, 0, 0, 0, 0, 1, 0 },
                     { 0, 0, 0, 0, 0, 0, 1 }};
  
    // Loop to find the power
    while (p != 1)
    {
        if (p % 2 == 1)
            s = matrix_product(s, mul);
        mul = matrix_product(mul, mul);
        p /= 2;
    }
    return matrix_product(mul, s);
}
  
// Function to return the required count
static double expectedSteps(int x)
{
  
    // Base cases
    if (x == 0)
        return 0;
    if (x <= 6)
        return 6;
  
    // Multiplier matrix
    double [][]mul = { { (double)7 / 6, 1, 0, 0, 0, 0, 0 },
                                   { 0, 0, 1, 0, 0, 0, 0 },
                                   { 0, 0, 0, 1, 0, 0, 0 },
                                   { 0, 0, 0, 0, 1, 0, 0 },
                                   { 0, 0, 0, 0, 0, 1, 0 },
                                   { 0, 0, 0, 0, 0, 0, 1 },
                                   {(double) - 1 / 6, 0, 0
                                                0, 0, 0, 0 }};
  
    // Finding the required multiplier
    // i.e mul^(X-6)
    mul = mul_expo(mul, x - 6);
  
    // Final answer
    return (mul[0][0] + mul[1][0] + mul[2][0] + 
            mul[3][0] + mul[4][0] + mul[5][0]) * 6;
}
  
// Driver code
public static void main(String[] args)
{
    int n = 10;
  
    System.out.printf("%.5f",expectedSteps(n - 1));
}
}
  
// This code is contributed by PrinciRaj1992

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 implementation of the approach 
import numpy as np
  
maxSize = 50
  
# Function to multiply two 7 * 7 matrix 
def matrix_product(a, b) :
    c = np.zeros((7, 7));
      
    for i in range(7) :
        for j in range(7) :
            for k in range(7) :
                c[i][j] += a[i][k] * b[k][j]; 
    return c
  
# Function to perform matrix exponentiation 
def mul_expo(mul, p) :
  
  
    # 7 * 7 identity matrix 
    s = [ [ 1, 0, 0, 0, 0, 0, 0 ], 
          [ 0, 1, 0, 0, 0, 0, 0 ], 
          [ 0, 0, 1, 0, 0, 0, 0 ], 
          [ 0, 0, 0, 1, 0, 0, 0 ],
          [ 0, 0, 0, 0, 1, 0, 0 ], 
          [ 0, 0, 0, 0, 0, 1, 0 ], 
          [ 0, 0, 0, 0, 0, 0, 1 ] ]; 
  
    # Loop to find the power 
    while (p != 1) :
        if (p % 2 == 1) :
            s = matrix_product(s, mul); 
              
        mul = matrix_product(mul, mul); 
        p //= 2
  
    return matrix_product(mul, s); 
  
# Function to return the required count 
def expectedSteps(x) : 
  
    # Base cases 
    if (x == 0) :
        return 0
          
    if (x <= 6) :
        return 6
  
    # Multiplier matrix 
    mul = [ [ 7 / 6, 1, 0, 0, 0, 0, 0 ], 
            [ 0, 0, 1, 0, 0, 0, 0 ], 
            [ 0, 0, 0, 1, 0, 0, 0 ], 
            [ 0, 0, 0, 0, 1, 0, 0 ], 
            [ 0, 0, 0, 0, 0, 1, 0 ], 
            [ 0, 0, 0, 0, 0, 0, 1 ], 
            [ -1 / 6, 0, 0, 0, 0, 0, 0 ] ]; 
  
    # Finding the required multiplier 
    # i.e mul^(X-6) 
    mul = mul_expo(mul, x - 6); 
  
    # Final answer 
    return (mul[0][0] + mul[1][0] + mul[2][0] + 
            mul[3][0] + mul[4][0] + mul[5][0]) * 6
  
# Driver code 
if __name__ == "__main__"
  
    n = 10
  
    print(expectedSteps(n - 1)); 
      
# This code is contributed by AnkitRai01

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# implementation of the approach
using System;
  
class GFG
{
static readonly int maxSize = 50;
  
// Function to multiply two 7 * 7 matrix
static double [,] matrix_product(double [,] a,
                                 double [,] b)
{
    double [,] c = new double[7, 7];
  
    for (int i = 0; i < 7; i++)
        for (int j = 0; j < 7; j++)
            for (int k = 0; k < 7; k++)
                c[i, j] += a[i, k] * b[k, j];
    return c;
}
  
// Function to perform matrix exponentiation
static double [,] mul_expo(double [,] mul, int p)
{
  
    // 7 * 7 identity matrix
    double [,] s = {{ 1, 0, 0, 0, 0, 0, 0 },
                    { 0, 1, 0, 0, 0, 0, 0 },
                    { 0, 0, 1, 0, 0, 0, 0 },
                    { 0, 0, 0, 1, 0, 0, 0 },
                    { 0, 0, 0, 0, 1, 0, 0 },
                    { 0, 0, 0, 0, 0, 1, 0 },
                    { 0, 0, 0, 0, 0, 0, 1 }};
  
    // Loop to find the power
    while (p != 1)
    {
        if (p % 2 == 1)
            s = matrix_product(s, mul);
        mul = matrix_product(mul, mul);
        p /= 2;
    }
    return matrix_product(mul, s);
}
  
// Function to return the required count
static double expectedSteps(int x)
{
  
    // Base cases
    if (x == 0)
        return 0;
    if (x <= 6)
        return 6;
  
    // Multiplier matrix
    double [,]mul = {{(double)7 / 6, 1, 0, 0, 0, 0, 0 },
                                { 0, 0, 1, 0, 0, 0, 0 },
                                { 0, 0, 0, 1, 0, 0, 0 },
                                { 0, 0, 0, 0, 1, 0, 0 },
                                { 0, 0, 0, 0, 0, 1, 0 },
                                { 0, 0, 0, 0, 0, 0, 1 },
                                {(double) - 1 / 6, 0, 0, 
                                                0, 0, 0, 0 }};
  
    // Finding the required multiplier
    // i.e mul^(X-6)
    mul = mul_expo(mul, x - 6);
  
    // Final answer
    return (mul[0, 0] + mul[1, 0] + mul[2, 0] + 
            mul[3, 0] + mul[4, 0] + mul[5, 0]) * 6;
}
  
// Driver code
public static void Main(String[] args)
{
    int n = 10;
  
    Console.Write("{0:f5}", expectedSteps(n - 1));
}
}
  
// This code is contributed by Rajput-Ji

chevron_right


Output:

7.36111

Time Complexity of the above approach will be O(343 * log(N)) or simply O(log(N)).

GeeksforGeeks has prepared a complete interview preparation course with premium videos, theory, practice problems, TA support and many more features. Please refer Placement 100 for details




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.