正好有k个硬币的路径数

给定一个矩阵,其中每个单元格都有一定数量的硬币。数一数从左上角到右下角的方法,精确到k个硬币。我们可以从一个单元(i,j)移动到(i+1,j)和(i,j+1)。

null

例子:

Input:  k = 12        mat[][] = { {1, 2, 3},                    {4, 6, 5},                    {3, 2, 1}                  };Output:  2There are two paths with 12 coins1 -> 2 -> 6 -> 2 -> 11 -> 2 -> 3 -> 5 -> 1

我们强烈建议您在继续解决方案之前单击此处并进行练习。

上述问题可递归定义如下:

pathCount(m, n, k):   Number of paths to reach mat[m][n] from mat[0][0]                       with exactly k coinsIf (m == 0 and n == 0)   return 1 if mat[0][0] == k else return 0Else:    pathCount(m, n, k) = pathCount(m-1, n, k - mat[m][n]) +                          pathCount(m, n-1, k - mat[m][n]) 

下面是上述递归算法的实现。

C++

// A Naive Recursive C++ program
// to count paths with exactly
// 'k' coins
#include <bits/stdc++.h>
#define R 3
#define C 3
using namespace std;
// Recursive function to count paths with sum k from
// (0, 0) to (m, n)
int pathCountRec( int mat[][C], int m, int n, int k)
{
// Base cases
if (m < 0 || n < 0) return 0;
if (m==0 && n==0) return (k == mat[m][n]);
// (m, n) can be reached either through (m-1, n) or
// through (m, n-1)
return pathCountRec(mat, m-1, n, k-mat[m][n]) +
pathCountRec(mat, m, n-1, k-mat[m][n]);
}
// A wrapper over pathCountRec()
int pathCount( int mat[][C], int k)
{
return pathCountRec(mat, R-1, C-1, k);
}
// Driver program
int main()
{
int k = 12;
int mat[R][C] = { {1, 2, 3},
{4, 6, 5},
{3, 2, 1}
};
cout << pathCount(mat, k);
return 0;
}


JAVA

// A Naive Recursive Java program to
// count paths with exactly 'k' coins
class GFG {
static final int R = 3 ;
static final int C = 3 ;
// Recursive function to count paths with sum k from
// (0, 0) to (m, n)
static int pathCountRec( int mat[][], int m, int n, int k) {
// Base cases
if (m < 0 || n < 0 ) {
return 0 ;
}
if (m == 0 && n == 0 && (k == mat[m][n])) {
return 1 ;
}
// (m, n) can be reached either through (m-1, n) or
// through (m, n-1)
return pathCountRec(mat, m - 1 , n, k - mat[m][n])
+ pathCountRec(mat, m, n - 1 , k - mat[m][n]);
}
// A wrapper over pathCountRec()
static int pathCount( int mat[][], int k) {
return pathCountRec(mat, R - 1 , C - 1 , k);
}
// Driver code
public static void main(String[] args) {
int k = 12 ;
int mat[][] = {{ 1 , 2 , 3 },
{ 4 , 6 , 5 },
{ 3 , 2 , 1 }
};
System.out.println(pathCount(mat, k));
}
}
/* This Java code is contributed by Rajput-Ji*/


Python3

# A Naive Recursive Python program to
# count paths with exactly 'k' coins
R = 3
C = 3
# Recursive function to count paths
# with sum k from (0, 0) to (m, n)
def pathCountRec(mat, m, n, k):
# Base cases
if m < 0 or n < 0 :
return 0
else if m = = 0 and n = = 0 :
return k = = mat[m][n]
# #(m, n) can be reached either
# through (m-1, n) or through
# (m, n-1)
return (pathCountRec(mat, m - 1 , n, k - mat[m][n])
+ pathCountRec(mat, m, n - 1 , k - mat[m][n]))
# A wrapper over pathCountRec()
def pathCount(mat, k):
return pathCountRec(mat, R - 1 , C - 1 , k)
# Driver Program
k = 12
mat = [[ 1 , 2 , 3 ],
[ 4 , 6 , 5 ],
[ 3 , 2 , 1 ]]
print (pathCount(mat, k))
# This code is contributed by Shrikant13.


C#

using System;
// A Naive Recursive c# program to
// count paths with exactly 'k' coins
public class GFG
{
public const int R = 3;
public const int C = 3;
// Recursive function to count paths with sum k from
// (0, 0) to (m, n)
public static int pathCountRec( int [][] mat, int m, int n, int k)
{
// Base cases
if (m < 0 || n < 0)
{
return 0;
}
if (m == 0 && n == 0 && (k == mat[m][n]))
{
return 1;
}
// (m, n) can be reached either through (m-1, n) or
// through (m, n-1)
return pathCountRec(mat, m - 1, n, k - mat[m][n])
+ pathCountRec(mat, m, n - 1, k - mat[m][n]);
}
// A wrapper over pathCountRec()
public static int pathCount( int [][] mat, int k)
{
return pathCountRec(mat, R - 1, C - 1, k);
}
// Driver code
public static void Main( string [] args)
{
int k = 12;
int [][] mat = new int [][]
{
new int [] {1, 2, 3},
new int [] {4, 6, 5},
new int [] {3, 2, 1}
};
Console.WriteLine(pathCount(mat, k));
}
}
// This code is contributed by Shrikant13


PHP

<?php
// A Naive Recursive PHP program to
// count paths with exactly 'k' coins
$R = 3;
$C = 3;
// Recursive function to count paths
// with sum k from (0, 0) to (m, n)
function pathCountRec( $mat , $m , $n , $k )
{
// Base cases
if ( $m < 0 or $n < 0)
return 0;
if ( $m == 0 and $n == 0)
return ( $k == $mat [ $m ][ $n ]);
// (m, n) can be reached either
// through (m-1, n) or through
// (m, n-1)
return pathCountRec( $mat , $m - 1,
$n , $k - $mat [ $m ][ $n ])
+ pathCountRec( $mat , $m ,
$n - 1, $k - $mat [ $m ][ $n ]);
}
// A wrapper over pathCountRec()
function pathCount( $mat , $k )
{
global $R , $C ;
return pathCountRec( $mat , $R -1,
$C -1, $k );
}
// Driver program
$k = 12;
$mat = array ( array (1, 2, 3),
array (4, 6, 5),
array (3, 2, 1) );
echo pathCount( $mat , $k );
// This code is contributed by anuj_67.
?>


Javascript

<script>
// A Naive Recursive Javascript program
// to count paths with exactly
// 'k' coins
let R = 3;
let C = 3;
// Recursive function to count paths with
// sum k from (0, 0) to (m, n)
function pathCountRec(mat, m, n, k)
{
// Base cases
if (m < 0 || n < 0)
return 0;
if (m == 0 && n == 0)
return (k == mat[m][n]);
// (m, n) can be reached either through (m-1, n) or
// through (m, n-1)
return pathCountRec(mat, m - 1, n, k - mat[m][n]) +
pathCountRec(mat, m, n - 1, k - mat[m][n]);
}
// A wrapper over pathCountRec()
function pathCount(mat, k)
{
return pathCountRec(mat, R - 1, C - 1, k);
}
// Driver code
let k = 12;
let mat = [ [ 1, 2, 3 ],
[ 4, 6, 5 ],
[ 3, 2, 1 ] ];
document.write(pathCount(mat, k));
// This code is contributed by divyesh072019
</script>


输出:

2

上述解的时间复杂度是指数的。我们可以在短期内解决这个问题 伪多项式时间 (时间复杂度取决于输入的数值)使用动态规划。这个想法是使用一个三维表dp[m][n][k],其中m是行数,n是列数,k是硬币数。下面是基于动态规划的实现。

C++

// A Dynamic Programming based C++ program to count paths with
// exactly 'k' coins
#include <bits/stdc++.h>
#define R 3
#define C 3
#define MAX_K 1000
using namespace std;
int dp[R][C][MAX_K];
int pathCountDPRecDP( int mat[][C], int m, int n, int k)
{
// Base cases
if (m < 0 || n < 0) return 0;
if (m==0 && n==0) return (k == mat[m][n]);
// If this subproblem is already solved
if (dp[m][n][k] != -1) return dp[m][n][k];
// (m, n) can be reached either through (m-1, n) or
// through (m, n-1)
dp[m][n][k] = pathCountDPRecDP(mat, m-1, n, k-mat[m][n]) +
pathCountDPRecDP(mat, m, n-1, k-mat[m][n]);
return dp[m][n][k];
}
// This function mainly initializes dp[][][] and calls
// pathCountDPRecDP()
int pathCountDP( int mat[][C], int k)
{
memset (dp, -1, sizeof dp);
return pathCountDPRecDP(mat, R-1, C-1, k);
}
// Driver Program to test above functions
int main()
{
int k = 12;
int mat[R][C] = { {1, 2, 3},
{4, 6, 5},
{3, 2, 1}
};
cout << pathCountDP(mat, k);
return 0;
}


JAVA

// A Dynamic Programming based JAVA program to count paths with
// exactly 'k' coins
class GFG
{
static final int R = 3 ;
static final int C = 3 ;
static final int MAX_K = 100 ;
static int [][][]dp= new int [R][C][MAX_K];
static int pathCountDPRecDP( int [][]mat, int m, int n, int k)
{
// Base cases
if (m < 0 || n < 0 ) return 0 ;
if (m== 0 && n== 0 ) return (k == mat[m][n] ? 1 : 0 );
// If this subproblem is already solved
if (dp[m][n][k] != - 1 ) return dp[m][n][k];
// (m, n) can be reached either through (m-1, n) or
// through (m, n-1)
dp[m][n][k] = pathCountDPRecDP(mat, m- 1 , n, k-mat[m][n]) +
pathCountDPRecDP(mat, m, n- 1 , k-mat[m][n]);
return dp[m][n][k];
}
// This function mainly initializes dp[][][] and calls
// pathCountDPRecDP()
static int pathCountDP( int [][]mat, int k)
{
for ( int i= 0 ;i<R;i++)
for ( int j= 0 ;j<C;j++)
for ( int l= 0 ;l<MAX_K;l++)
dp[i][j][l]=- 1 ;
return pathCountDPRecDP(mat, R- 1 , C- 1 , k);
}
// Driver Program to test above functions
public static void main(String []args)
{
int k = 12 ;
int [][] mat = new int [][]
{
new int [] { 1 , 2 , 3 },
new int [] { 4 , 6 , 5 },
new int [] { 3 , 2 , 1 }
};
System.out.println(pathCountDP(mat, k));
}
}
// This code is contributed by ihritik


Python3

# A Dynamic Programming based Python3 program to
# count paths with exactly 'k' coins
R = 3
C = 3
MAX_K = 1000
def pathCountDPRecDP(mat, m, n, k):
# Base cases
if m < 0 or n < 0 :
return 0
else if m = = 0 and n = = 0 :
return k = = mat[m][n]
# If this subproblem is already solved
if (dp[m][n][k] ! = - 1 ):
return dp[m][n][k]
# #(m, n) can be reached either
# through (m-1, n) or through
# (m, n-1)
dp[m][n][k] = (pathCountDPRecDP(mat, m - 1 , n, k - mat[m][n]) +
pathCountDPRecDP(mat, m, n - 1 , k - mat[m][n]))
return dp[m][n][k]
# A wrapper over pathCountDPRecDP()
def pathCountDP(mat, k):
return pathCountDPRecDP(mat, R - 1 , C - 1 , k)
# Driver Code
k = 12
# Initialising dp[][][]
dp = [[ [ - 1 for col in range (MAX_K)]
for col in range (C)]
for row in range (R)]
mat = [[ 1 , 2 , 3 ],
[ 4 , 6 , 5 ],
[ 3 , 2 , 1 ]]
print (pathCountDP(mat, k))
# This code is contributed by ashutosh450


C#

// A Dynamic Programming based C# program
// to count paths with exactly 'k' coins
using System;
class GFG
{
static readonly int R = 3;
static readonly int C = 3;
static readonly int MAX_K = 100;
static int [,,]dp = new int [R, C, MAX_K];
static int pathCountDPRecDP( int [,]mat, int m,
int n, int k)
{
// Base cases
if (m < 0 || n < 0) return 0;
if (m == 0 && n == 0)
return (k == mat[m, n] ? 1 : 0);
// If this subproblem is already solved
if (dp[m, n, k] != -1) return dp[m, n, k];
// (m, n) can be reached either through (m-1, n) or
// through (m, n-1)
dp[m, n, k] = pathCountDPRecDP(mat, m - 1, n, k - mat[m, n]) +
pathCountDPRecDP(mat, m, n - 1, k - mat[m, n]);
return dp[m, n, k];
}
// This function mainly initializes [,]dp[] and
// calls pathCountDPRecDP()
static int pathCountDP( int [,]mat, int k)
{
for ( int i = 0; i < R; i++)
for ( int j = 0; j < C; j++)
for ( int l = 0; l < MAX_K; l++)
dp[i, j, l] = -1;
return pathCountDPRecDP(mat, R - 1, C - 1, k);
}
// Driver Code
public static void Main(String []args)
{
int k = 12;
int [,] mat = { {1, 2, 3},
{4, 6, 5},
{3, 2, 1}};
Console.WriteLine(pathCountDP(mat, k));
}
}
// This code is contributed by PrinciRaj1992


Javascript

<script>
// A Dynamic Programming based javascript program to count paths with
// exactly 'k' coins
var R = 3;
var C = 3;
var MAX_K = 100;
var dp = Array(R).fill().map(()=>Array(C).fill().map(()=>Array(MAX_K).fill(0)));
function pathCountDPRecDP(mat , m , n , k) {
// Base cases
if (m < 0 || n < 0)
return 0;
if (m == 0 && n == 0)
return (k == mat[m][n] ? 1 : 0);
// If this subproblem is already solved
if (dp[m][n][k] != -1)
return dp[m][n][k];
// (m, n) can be reached either through (m-1, n) or
// through (m, n-1)
dp[m][n][k] = pathCountDPRecDP(mat, m - 1, n, k - mat[m][n]) + pathCountDPRecDP(mat, m, n - 1, k - mat[m][n]);
return dp[m][n][k];
}
// This function mainly initializes dp and calls
// pathCountDPRecDP()
function pathCountDP(mat , k) {
for (i = 0; i < R; i++)
for (j = 0; j < C; j++)
for (l = 0; l < MAX_K; l++)
dp[i][j][l] = -1;
return pathCountDPRecDP(mat, R - 1, C - 1, k);
}
// Driver Program to test above functions
var k = 12;
var mat = [[ 1, 2, 3 ],[ 4, 6, 5 ], [ 3, 2, 1 ] ];
document.write(pathCountDP(mat, k));
// This code contributed by aashish1995
</script>


输出:

2

该解的时间复杂度为O(m*n*k)。 感谢Gaurav Ahirwar提出上述解决方案。 如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写评论

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享