Ймовірність Лицаря залишитися на шахівниці
Враховуючи а п*н шахівниця і лицар положення (x y) кожного разу, коли конь має ходити, він вибирає один із восьми можливих ходів рівномірно випадковий (навіть якщо фігура зійде з шахівниці) і рухається там. лицар продовжується рухаючись, доки не буде зроблено точно k рухається або має рушив шахова дошка. Завдання полягає в тому, щоб знайти в ймовірність що лицар залишається на дошка після того, як він має зупинився переміщення.
Примітка: Шаховий конь може зробити вісім можливих ходів. Кожен хід складається з двох клітинок у кардинальному напрямку, а потім однієї клітинки в ортогональному напрямку.
приклади:
введення: n = 8 x = 0 y = 0 k = 1
Вихід: 0,25
Пояснення: Лицар починає з (0 0) і, зробивши один крок, він лежатиме всередині дошки лише у 2 із 8 позицій, а саме (1 2) і (2 1). Таким чином, ймовірність буде 2/8 = 0,25.Вхідні дані: n = 8 x = 0 y = 0 k = 3
Вихід: 0,125введення: n = 4 x = 1 y = 2 k = 4
Вихід: 0,024414
Зміст
- Використання Dp зверху вниз (запам'ятовування) - O(n*n*k) часу та O(n*n*k) простору
- Використання Bottom-Up Dp (табуляції) - O(n*n*k) часу та O(n*n*k) простору
- Використання оптимізованого простору Dp - O(n*n*k) часу та O(n*n) простору
Використання Dp зверху вниз (запам'ятовування) - O(n*n*k) часу та O(n*n*k) простору
C++Ймовірність того, що конь залишиться на шахівниці після k ходів, дорівнює середньому значенню ймовірності коня на попередніх восьми позиціях після k - 1 ходів. Так само ймовірність після k-1 ходів залежить від середньої ймовірності після k-2 ходів. Ідея полягає в тому, щоб використовувати запам'ятовування зберігати ймовірності попередніх ходів і знаходити їхнє середнє для обчислення кінцевого результату.
Для цього створіть a Пам'ятка про 3d-масив[][][] де memo[i][j][k] зберігає ймовірність коня опинитися в клітинці (i j) після k ходів. Якщо k дорівнює нулю, тобто досягнуто початкового стану повернення 1 інакше дослідіть попередні вісім позицій і знайдіть середнє значення їх ймовірностей.
// C++ program to find the probability of the // knight to remain inside the chessboard #include using namespace std ; // recursive function to calculate // knight probability double knightProbability ( int n int x int y int k vector < vector < vector < double >>> & memo ){ // Base case initial probability if ( k == 0 ) return 1.0 ; // check if already calculated if ( memo [ x ][ y ][ k ] != -1 ) return memo [ x ][ y ][ k ]; vector < vector < int >> directions = {{ 1 2 } { 2 1 } { 2 -1 } { 1 -2 } { -1 -2 } { -2 -1 } { -2 1 } { -1 2 }}; memo [ x ][ y ][ k ] = 0 ; double cur = 0.0 ; // for every position reachable from (xy) for ( auto d : directions ){ int u = x + d [ 0 ]; int v = y + d [ 1 ]; // if this position lie inside the board if ( u >= 0 && u < n && v >= 0 && v < n ) cur += knightProbability ( n u v k -1 memo ) / 8.0 ; } return memo [ x ][ y ][ k ] = cur ; } // Function to find the probability double findProb ( int n int x int y int k ) { // Initialize memo to store results vector < vector < vector < double >>> memo ( n vector < vector < double >> ( n vector < double > ( k + 1 -1 ))); return knightProbability ( n x y k memo ); } int main (){ int n = 8 x = 0 y = 0 k = 3 ; cout < < findProb ( n x y k ) < < endl ; return 0 ; }
Java // Java program to find the probability of the // knight to remain inside the chessboard class GfG { // recursive function to calculate // knight probability static double knightProbability ( int n int x int y int k double [][][] memo ) { // Base case initial probability if ( k == 0 ) return 1.0 ; // check if already calculated if ( memo [ x ][ y ][ k ] != - 1 ) return memo [ x ][ y ][ k ] ; int [][] directions = {{ 1 2 } { 2 1 } { 2 - 1 } { 1 - 2 } { - 1 - 2 } { - 2 - 1 } { - 2 1 } { - 1 2 }}; memo [ x ][ y ][ k ] = 0 ; double cur = 0.0 ; // for every position reachable from (x y) for ( int [] d : directions ) { int u = x + d [ 0 ] ; int v = y + d [ 1 ] ; // if this position lies inside the board if ( u >= 0 && u < n && v >= 0 && v < n ) cur += knightProbability ( n u v k - 1 memo ) / 8.0 ; } return memo [ x ][ y ][ k ] = cur ; } // Function to find the probability static double findProb ( int n int x int y int k ) { // Initialize memo to store results double [][][] memo = new double [ n ][ n ][ k + 1 ] ; for ( int i = 0 ; i < n ; i ++ ) { for ( int j = 0 ; j < n ; j ++ ) { for ( int m = 0 ; m <= k ; m ++ ) { memo [ i ][ j ][ m ] = - 1 ; } } } return knightProbability ( n x y k memo ); } public static void main ( String [] args ) { int n = 8 x = 0 y = 0 k = 3 ; System . out . println ( findProb ( n x y k )); } }
Python # Python program to find the probability of the # knight to remain inside the chessboard # recursive function to calculate # knight probability def knightProbability ( n x y k memo ): # Base case initial probability if k == 0 : return 1.0 # check if already calculated if memo [ x ][ y ][ k ] != - 1 : return memo [ x ][ y ][ k ] directions = [ [ 1 2 ] [ 2 1 ] [ 2 - 1 ] [ 1 - 2 ] [ - 1 - 2 ] [ - 2 - 1 ] [ - 2 1 ] [ - 1 2 ] ] memo [ x ][ y ][ k ] = 0 cur = 0.0 # for every position reachable from (x y) for d in directions : u = x + d [ 0 ] v = y + d [ 1 ] # if this position lies inside the board if 0 <= u < n and 0 <= v < n : cur += knightProbability ( n u v k - 1 memo ) / 8.0 memo [ x ][ y ][ k ] = cur return cur # Function to find the probability def findProb ( n x y k ): # Initialize memo to store results memo = [[[ - 1 for _ in range ( k + 1 )] for _ in range ( n )] for _ in range ( n )] return knightProbability ( n x y k memo ) n x y k = 8 0 0 3 print ( findProb ( n x y k ))
C# // C# program to find the probability of the // knight to remain inside the chessboard using System ; class GfG { // recursive function to calculate // knight probability static double KnightProbability ( int n int x int y int k double [] memo ) { // Base case initial probability if ( k == 0 ) return 1.0 ; // check if already calculated if ( memo [ x y k ] != - 1 ) return memo [ x y k ]; int [] directions = {{ 1 2 } { 2 1 } { 2 - 1 } { 1 - 2 } { - 1 - 2 } { - 2 - 1 } { - 2 1 } { - 1 2 }}; memo [ x y k ] = 0 ; double cur = 0.0 ; // for every position reachable from (x y) for ( int i = 0 ; i < 8 ; i ++ ) { int u = x + directions [ i 0 ]; int v = y + directions [ i 1 ]; // if this position lies inside the board if ( u >= 0 && u < n && v >= 0 && v < n ) { cur += KnightProbability ( n u v k - 1 memo ) / 8.0 ; } } return memo [ x y k ] = cur ; } // Function to find the probability static double FindProb ( int n int x int y int k ) { // Initialize memo to store results double [] memo = new double [ n n k + 1 ]; for ( int i = 0 ; i < n ; i ++ ) { for ( int j = 0 ; j < n ; j ++ ) { for ( int m = 0 ; m <= k ; m ++ ) { memo [ i j m ] = - 1 ; } } } return KnightProbability ( n x y k memo ); } static void Main () { int n = 8 x = 0 y = 0 k = 3 ; Console . WriteLine ( FindProb ( n x y k )); } }
JavaScript // JavaScript program to find the probability of the // knight to remain inside the chessboard // recursive function to calculate // knight probability function knightProbability ( n x y k memo ) { // Base case initial probability if ( k === 0 ) return 1.0 ; // check if already calculated if ( memo [ x ][ y ][ k ] !== - 1 ) return memo [ x ][ y ][ k ]; const directions = [ [ 1 2 ] [ 2 1 ] [ 2 - 1 ] [ 1 - 2 ] [ - 1 - 2 ] [ - 2 - 1 ] [ - 2 1 ] [ - 1 2 ] ]; memo [ x ][ y ][ k ] = 0 ; let cur = 0.0 ; // for every position reachable from (x y) for ( let d of directions ) { const u = x + d [ 0 ]; const v = y + d [ 1 ]; // if this position lies inside the board if ( u >= 0 && u < n && v >= 0 && v < n ) { cur += knightProbability ( n u v k - 1 memo ) / 8.0 ; } } return memo [ x ][ y ][ k ] = cur ; } // Function to find the probability function findProb ( n x y k ) { // Initialize memo to store results const memo = Array . from ({ length : n } () => Array . from ({ length : n } () => Array ( k + 1 ). fill ( - 1 ))); return knightProbability ( n x y k memo ). toFixed ( 6 ); } const n = 8 x = 0 y = 0 k = 3 ; console . log ( findProb ( n x y k ));
Вихід
0.125
Використання Bottom-Up Dp (табуляції) - O(n*n*k) часу та O(n*n*k) простору
C++Наведений вище підхід можна оптимізувати за допомогою знизу вгору табуляція зменшує додатковий простір, необхідний для рекурсивного стеку. Ідея полягає в тому, щоб зберегти 3 D масив dp[][][] де dp[i][j][k] зберігає ймовірність перебування лицаря в клітинці (i j) після k рухається. Ініціалізувати 0-й стан dp зі значенням 1 . Для кожного наступного ходу ймовірність лицаря буде рівні до середній ймовірність попередній 8 позиція після k-1 рухається.
// C++ program to find the probability of the // knight to remain inside the chessboard #include using namespace std ; // Function to find the probability double findProb ( int n int x int y int k ) { // Initialize dp to store results of each step vector < vector < vector < double >>> dp ( n vector < vector < double >> ( n vector < double > ( k + 1 ))); // Initialize dp for step 0 for ( int i = 0 ; i < n ; ++ i ) { for ( int j = 0 ; j < n ; ++ j ) { dp [ i ][ j ][ 0 ] = 1.0 ; } } vector < vector < int >> directions = { { 1 2 } { 2 1 } { 2 -1 } { 1 -2 } { -1 -2 } { -2 -1 } { -2 1 } { -1 2 } }; for ( int move = 1 ; move <= k ; move ++ ) { // find probability for cell (i j) for ( int i = 0 ; i < n ; ++ i ) { for ( int j = 0 ; j < n ; ++ j ) { double cur = 0.0 ; // for every position reachable from (xy) for ( auto d : directions ) { int u = i + d [ 0 ]; int v = j + d [ 1 ]; // if this position lie inside the board if ( u >= 0 && u < n && v >= 0 && v < n ) cur += dp [ u ][ v ][ move - 1 ] / 8.0 ; } // store the result dp [ i ][ j ][ move ] = cur ; } } } // return the result return dp [ x ][ y ][ k ]; } int main (){ int n = 8 x = 0 y = 0 k = 3 ; cout < < findProb ( n x y k ) < < endl ; return 0 ; }
Java // Java program to find the probability of the // knight to remain inside the chessboard import java.util.* ; class GfG { // Function to find the probability static double findProb ( int n int x int y int k ) { // Initialize dp to store results of each step double [][][] dp = new double [ n ][ n ][ k + 1 ] ; for ( int i = 0 ; i < n ; i ++ ) { for ( int j = 0 ; j < n ; j ++ ) { dp [ i ][ j ][ 0 ] = 1 ; } } int [][] directions = { { 1 2 } { 2 1 } { 2 - 1 } { 1 - 2 } { - 1 - 2 } { - 2 - 1 } { - 2 1 } { - 1 2 } }; for ( int move = 1 ; move <= k ; move ++ ) { // find probability for cell (i j) for ( int i = 0 ; i < n ; ++ i ) { for ( int j = 0 ; j < n ; ++ j ) { double cur = 0.0 ; // for every position reachable from (x y) for ( int [] d : directions ) { int u = i + d [ 0 ] ; int v = j + d [ 1 ] ; // if this position lies inside the board if ( u >= 0 && u < n && v >= 0 && v < n ) { cur += dp [ u ][ v ][ move - 1 ] / 8.0 ; } } // store the result dp [ i ][ j ][ move ] = cur ; } } } // return the result return dp [ x ][ y ][ k ] ; } public static void main ( String [] args ) { int n = 8 x = 0 y = 0 k = 3 ; System . out . println ( findProb ( n x y k )); } }
Python # Python program to find the probability of the # knight to remain inside the chessboard # Function to find the probability def findProb ( n x y k ): # Initialize dp to store results of each step dp = [[[ 0 for _ in range ( k + 1 )] for _ in range ( n )] for _ in range ( n )] for i in range ( n ): for j in range ( n ): dp [ i ][ j ][ 0 ] = 1.0 directions = [[ 1 2 ] [ 2 1 ] [ 2 - 1 ] [ 1 - 2 ] [ - 1 - 2 ] [ - 2 - 1 ] [ - 2 1 ] [ - 1 2 ]] for move in range ( 1 k + 1 ): # find probability for cell (i j) for i in range ( n ): for j in range ( n ): cur = 0.0 # for every position reachable from (x y) for d in directions : u = i + d [ 0 ] v = j + d [ 1 ] # if this position lies inside the board if 0 <= u < n and 0 <= v < n : cur += dp [ u ][ v ][ move - 1 ] / 8.0 # store the result dp [ i ][ j ][ move ] = cur # return the result return dp [ x ][ y ][ k ] if __name__ == '__main__' : n x y k = 8 0 0 3 print ( findProb ( n x y k ))
C# // C# program to find the probability of the // knight to remain inside the chessboard using System ; class GfG { // Function to find the probability static double findProb ( int n int x int y int k ) { // Initialize dp to store results of each step double [] dp = new double [ n n k + 1 ]; for ( int i = 0 ; i < n ; i ++ ) { for ( int j = 0 ; j < n ; j ++ ) { dp [ i j 0 ] = 1.0 ; } } int [] directions = {{ 1 2 } { 2 1 } { 2 - 1 } { 1 - 2 } { - 1 - 2 } { - 2 - 1 } { - 2 1 } { - 1 2 }}; for ( int move = 1 ; move <= k ; move ++ ) { // find probability for cell (i j) for ( int i = 0 ; i < n ; ++ i ) { for ( int j = 0 ; j < n ; ++ j ) { double cur = 0.0 ; // for every position reachable from (x y) for ( int d = 0 ; d < directions . GetLength ( 0 ); d ++ ) { int u = i + directions [ d 0 ]; int v = j + directions [ d 1 ]; // if this position lies inside the board if ( u >= 0 && u < n && v >= 0 && v < n ) { cur += dp [ u v move - 1 ] / 8.0 ; } } // store the result dp [ i j move ] = cur ; } } } // return the result return dp [ x y k ]; } static void Main ( string [] args ) { int n = 8 x = 0 y = 0 k = 3 ; Console . WriteLine ( findProb ( n x y k )); } }
JavaScript // JavaScript program to find the probability of the // knight to remain inside the chessboard // Function to find the probability function findProb ( n x y k ) { // Initialize dp to store results of each step let dp = Array . from ({ length : n } () => Array . from ({ length : n } () => Array ( k + 1 ). fill ( 0 )) ); // Initialize dp for step 0 for ( let i = 0 ; i < n ; ++ i ) { for ( let j = 0 ; j < n ; ++ j ) { dp [ i ][ j ][ 0 ] = 1.0 ; } } let directions = [[ 1 2 ] [ 2 1 ] [ 2 - 1 ] [ 1 - 2 ] [ - 1 - 2 ] [ - 2 - 1 ] [ - 2 1 ] [ - 1 2 ]]; for ( let move = 1 ; move <= k ; move ++ ) { // find probability for cell (i j) for ( let i = 0 ; i < n ; i ++ ) { for ( let j = 0 ; j < n ; j ++ ) { let cur = 0.0 ; // for every position reachable from (x y) for ( let d of directions ) { let u = i + d [ 0 ]; let v = j + d [ 1 ]; // if this position lies inside the board if ( u >= 0 && u < n && v >= 0 && v < n ) { cur += dp [ u ][ v ][ move - 1 ] / 8.0 ; } } // store the result dp [ i ][ j ][ move ] = cur ; } } } // return the result return dp [ x ][ y ][ k ]. toFixed ( 6 ); } let n = 8 x = 0 y = 0 k = 3 ; console . log ( findProb ( n x y k ));
Вихід
0.125
Використання оптимізованого простору Dp - O(n*n*k) часу та O(n*n) простору
C++Вищеописаний підхід вимагає тільки попередній стан ймовірностей для розрахунку поточний стан таким чином тільки в попередній магазин потрібно зберігати. Ідея полягає в тому, щоб створити два Двомірні масиви prevMove[][] і currMove[][] де
- prevMove[i][j] зберігає ймовірність коня бути в (i j) до попереднього ходу. Він ініціалізується значенням 1 для початкового стану.
- currMove[i][j] зберігає ймовірність поточного стану.
Діють аналогічно описаному вище підходу і при кінець кожної ітерації оновити prevMove[][] зі значенням, що зберігається в currMove[][].
// C++ program to find the probability of the // knight to remain inside the chessboard #include using namespace std ; // Function to find the probability double findProb ( int n int x int y int k ) { // dp to store results of previous move vector < vector < double >> prevMove ( n vector < double > ( n 1 )); // dp to store results of current move vector < vector < double >> currMove ( n vector < double > ( n 0 )); vector < vector < int >> directions = { { 1 2 } { 2 1 } { 2 -1 } { 1 -2 } { -1 -2 } { -2 -1 } { -2 1 } { -1 2 } }; for ( int move = 1 ; move <= k ; move ++ ) { // find probability for cell (i j) for ( int i = 0 ; i < n ; ++ i ) { for ( int j = 0 ; j < n ; ++ j ) { double cur = 0.0 ; // for every position reachable from (xy) for ( auto d : directions ) { int u = i + d [ 0 ]; int v = j + d [ 1 ]; // if this position lie inside the board if ( u >= 0 && u < n && v >= 0 && v < n ) cur += prevMove [ u ][ v ] / 8.0 ; } // store the result currMove [ i ][ j ] = cur ; } } // update previous state prevMove = currMove ; } // return the result return prevMove [ x ][ y ]; } int main (){ int n = 8 x = 0 y = 0 k = 3 ; cout < < findProb ( n x y k ) < < endl ; return 0 ; }
Java // Java program to find the probability of the // knight to remain inside the chessboard class GfG { // Function to find the probability static double findProb ( int n int x int y int k ) { // dp to store results of previous move double [][] prevMove = new double [ n ][ n ] ; for ( int i = 0 ; i < n ; i ++ ) { for ( int j = 0 ; j < n ; j ++ ) { prevMove [ i ][ j ] = 1.0 ; } } // dp to store results of current move double [][] currMove = new double [ n ][ n ] ; int [][] directions = { { 1 2 } { 2 1 } { 2 - 1 } { 1 - 2 } { - 1 - 2 } { - 2 - 1 } { - 2 1 } { - 1 2 } }; for ( int move = 1 ; move <= k ; move ++ ) { // find probability for cell (i j) for ( int i = 0 ; i < n ; ++ i ) { for ( int j = 0 ; j < n ; ++ j ) { double cur = 0.0 ; // for every position reachable from (xy) for ( int [] d : directions ) { int u = i + d [ 0 ] ; int v = j + d [ 1 ] ; // if this position lies inside the board if ( u >= 0 && u < n && v >= 0 && v < n ) cur += prevMove [ u ][ v ] / 8.0 ; } // store the result currMove [ i ][ j ] = cur ; } } // update previous state for ( int i = 0 ; i < n ; i ++ ) { System . arraycopy ( currMove [ i ] 0 prevMove [ i ] 0 n ); } } // return the result return prevMove [ x ][ y ] ; } public static void main ( String [] args ) { int n = 8 x = 0 y = 0 k = 3 ; System . out . println ( findProb ( n x y k )); } }
Python # Python program to find the probability of the # knight to remain inside the chessboard def findProb ( n x y k ): # dp to store results of previous move prevMove = [[ 1.0 ] * n for _ in range ( n )] # dp to store results of current move currMove = [[ 0.0 ] * n for _ in range ( n )] directions = [ [ 1 2 ] [ 2 1 ] [ 2 - 1 ] [ 1 - 2 ] [ - 1 - 2 ] [ - 2 - 1 ] [ - 2 1 ] [ - 1 2 ] ] for move in range ( 1 k + 1 ): # find probability for cell (i j) for i in range ( n ): for j in range ( n ): cur = 0.0 # for every position reachable from (xy) for d in directions : u v = i + d [ 0 ] j + d [ 1 ] # if this position lies inside the board if 0 <= u < n and 0 <= v < n : cur += prevMove [ u ][ v ] / 8.0 # store the result currMove [ i ][ j ] = cur # update previous state prevMove = [ row [:] for row in currMove ] # return the result return prevMove [ x ][ y ] if __name__ == '__main__' : n x y k = 8 0 0 3 print ( findProb ( n x y k ))
C# // C# program to find the probability of the // knight to remain inside the chessboard using System ; class GfG { // Function to find the probability static double findProb ( int n int x int y int k ) { // dp to store results of previous move double [] prevMove = new double [ n n ]; for ( int i = 0 ; i < n ; i ++ ) for ( int j = 0 ; j < n ; j ++ ) prevMove [ i j ] = 1.0 ; // dp to store results of current move double [] currMove = new double [ n n ]; int [] directions = { { 1 2 } { 2 1 } { 2 - 1 } { 1 - 2 } { - 1 - 2 } { - 2 - 1 } { - 2 1 } { - 1 2 } }; for ( int move = 1 ; move <= k ; move ++ ) { // find probability for cell (i j) for ( int i = 0 ; i < n ; ++ i ) { for ( int j = 0 ; j < n ; ++ j ) { double cur = 0.0 ; // for every position reachable from (xy) for ( int d = 0 ; d < directions . GetLength ( 0 ); d ++ ) { int u = i + directions [ d 0 ]; int v = j + directions [ d 1 ]; // if this position lies inside the board if ( u >= 0 && u < n && v >= 0 && v < n ) cur += prevMove [ u v ] / 8.0 ; } // store the result currMove [ i j ] = cur ; } } // update previous state Array . Copy ( currMove prevMove n * n ); } // return the result return prevMove [ x y ]; } static void Main () { int n = 8 x = 0 y = 0 k = 3 ; Console . WriteLine ( findProb ( n x y k )); } }
JavaScript // JavaScript program to find the probability of the // knight to remain inside the chessboard function findProb ( n x y k ) { // dp to store results of previous move let prevMove = Array . from ({ length : n } () => Array ( n ). fill ( 1.0 )); // dp to store results of current move let currMove = Array . from ({ length : n } () => Array ( n ). fill ( 0.0 )); const directions = [ [ 1 2 ] [ 2 1 ] [ 2 - 1 ] [ 1 - 2 ] [ - 1 - 2 ] [ - 2 - 1 ] [ - 2 1 ] [ - 1 2 ] ]; for ( let move = 1 ; move <= k ; move ++ ) { // find probability for cell (i j) for ( let i = 0 ; i < n ; i ++ ) { for ( let j = 0 ; j < n ; j ++ ) { let cur = 0.0 ; // for every position reachable from (xy) for ( let d of directions ) { let u = i + d [ 0 ]; let v = j + d [ 1 ]; // if this position lies inside the board if ( u >= 0 && u < n && v >= 0 && v < n ) cur += prevMove [ u ][ v ] / 8.0 ; } // store the result currMove [ i ][ j ] = cur ; } } // update previous state prevMove = currMove . map ( row => [... row ]); } // return the result return prevMove [ x ][ y ]. toFixed ( 6 ); } let n = 8 x = 0 y = 0 k = 3 ; console . log ( findProb ( n x y k ));
Вихід
0.125Створіть вікторину