给定一个矩阵,其中每个单元格都有一定数量的硬币。计算从左上角到右下方的确切
k
个硬币的数量。我们可以从单元格(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)
成为使用M[0][0]
硬币从M[i][j]
升级到k
的方式的数量。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,这是不正确的。
我想知道我的推理出错的地方以及如何解决。
答案 0 :(得分:2)
你的问题是
Count[0][0][1] = 1
Count[0][0][M[0][0]]
初始化Count[0][j]
(虽然这里的内容相同)Count[i][0]
或< N
,也就是说,您从任何正在循环的单元格中找不到0,0的完整路径M[i-1][j-1]
并且当向量为零索引时返回N-1 M[i][j]
的k M[i][j]
进行测试而不是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];
onTimerComplete
硬币(正如Edward和vu1p3n0x在评论中指出的那样)这是一个固定循环:
MainTimer
另外,也许我误解了:你是不是故意将左上角的方格数计为1,1这样你就不需要检查我们是否为你进行了i-1和j-1检查,因为那里总会有一排零溢出来?这对于我认为的返回[N] [N]和M [i-1] [j-1]是有意义的。在那种情况下,你想要