[英]Number of paths using k coins
给定一个矩阵,其中每个单元都有一定数量的硬币。 用正好
k
硬币计算从右上角到右下角的方式数。 我们可以从单元(i, j)
移至(i+1, j)
和(i, j+1)
(i, j)
。例:
输入:k = 12
mat[][] = { {1, 2, 3}, {4, 6, 5}, {3, 2, 1} };
输出:2有两条带有12个硬币的路径
1-> 2-> 6-> 2-> 1
1-> 2-> 3-> 5-> 1
我为此创建了一个递归定义:
令
Count(i, j, k)
为使用k
硬币从M[0][0]
到M[i][j]
方法数量。Count(i, j, k) = { 0: if M[i][j] > k, Count(i-1, j, k-1) + Count(i, j-1, k-1): if M[i][j] < k }
我对此定义的理由是,如果矩阵中的条目(硬币数量)大于我们想要的硬币数量( k
),则我们无法采用该路径,因此表中的值应为0。
如果条目小于或等于硬币数量,那么我们可以通过从顶部(i-1,j)
和左侧(i, j-1)
相加的路径数量来采用该路径。 我将k
减1,因为最后一次输入的硬币数量少了1。
这是我在以下动态编程功能中执行的操作:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define MAX_SIZE 10
#define MAX_COINS 20
int Count[MAX_SIZE][MAX_SIZE][MAX_COINS]; // number of ways to get from M[0][0] to M[i][j] using k coins
std::vector<std::vector<int>> M;
int NumOfPaths(int C) {
size_t N = M.size();
// Number of paths to (0,0) with 1 coin is 1
Count[0][0][1] = 1;
// zero coins doesn't work
for (size_t i = 0; i < N; ++i) for (size_t j = 0; j < N; ++j)
Count[i][j][0] = 0;
// If the number of coins is greater than the max then Count[i][j][k] = 0;
// Otherwise Count[i][j][k] = Count[i-1][j][k-1]+Count[i][j-1][k-1]
for (size_t i = 1; i <= N; ++i) {
for (size_t j = 1; j <= N; ++j) {
for (int k = 1; k <= C; ++k) {
if (M[i-1][j-1] > k) Count[i][j][k] = 0;
if (M[i-1][j-1] <= k) Count[i][j][k] = Count[i-1][j][k-1] + Count[i][j-1][k-1];
}
}
}
return Count[N][N][C];
}
int main() {
M = { {1, 2, 3},
{4, 6, 5},
{3, 2, 1}
};
cout << NumOfPaths(12);
}
当我将函数应用于问题陈述中给出的示例时,它返回0,这是不正确的。
我想知道我的推理哪里出了问题以及如何解决。
你的问题是
Count[0][0][1] = 1
时应为Count[0][0][M[0][0]]
(尽管此处相同) Count[0][j]
或Count[i][0]
,即您没有从循环到的任何单元格到0,0的完整路径 < N
并返回N-1,因为向量为零索引 M[i-1][j-1]
测试k,而不是M[i][j]
M[i][j]
硬币(如Edward和vu1p3n0x在评论中指出) 这是一个固定循环:
for (size_t i = 0; i < N; ++i) {
for (size_t j = 0; j < N; ++j) {
if ((i == 0) && (j == 0)) {
// Skip 0,0: we've populated that already
continue;
}
for (int k = 1; k <= C; ++k) {
if (M[i][j] > k) Count[i][j][k] = 0;
if (M[i][j] <= k) {
int ways = 0;
if (i >= 1) ways += Count[i - 1][j][k - M[i][j]];
if (j >= 1) ways += Count[i][j - 1][k - M[i][j]];
Count[i][j][k] = ways;
}
}
}
}
return Count[N-1][N-1][C];
或者,也许我误会了:您是否故意将左上角的平方算为1,1,以便您不需要检查i-1和j-1是否在边界内,因为总是一排零溅入? 对于我想的返回值[N] [N]和M [i-1] [j-1],这是有意义的。 在这种情况下,您想要
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.