华为面试2:1分2分5分的硬币,组成1角,共有多少种组合。

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

华为⾯试2:1分2分5分的硬币,组成1⾓,共有多少种组合。

动态规划,注意不要有重复的,例如组成1⾓钱,5 2 2 1 和 1 2 2 5是1种组合
算法的设计思想在程序中注释的很清楚。

解法⼀:
// 动态规划
// total_money: 要找的零钱总和
// changes: 零钱数组,已经从⼩到⼤排序,第1个元素设为0,有效元素从第2个位置即下标1开始
// kinds_change: 零钱种类
int make_change_problem(int total_money, int *changes, int kinds_change)
{
// opt[i][j]表⽰⽤前j种零钱组成i元钱的组合数⽬,第j种零钱的数⽬可以为0
boost::multi_array<int, 2> opt(boost::extents[total_money+1][kinds_change+1]);
int i, j;
// 组成0元钱的组合数⽬只有1种,即不选择任何零钱
i = 0;
for (j = 0; j <= kinds_change; ++j)
opt[i][j] = 1;
// ⽤0种零钱组成i(1<=i<=total_money)元钱的组合数⽬是0
j = 0;
for (i = 1; i <= total_money; ++i)
opt[i][j] = 0;
for (i = 1; i <= total_money; ++i)
{
for (j = 1; j <= kinds_change; ++j)
{
opt[i][j] = 0;
int K = i / changes[j]; // 第j种零钱的最⼤数⽬
for (int k = 0; k <= K; ++k)
opt[i][j] += opt[i-k*changes[j]][j-1];
}
}
return opt[total_money][kinds_change];
}
int main(int argc, char **argv)
{
int total_money = 10;
int changes[] = {0, 1, 2, 5};
int kinds_change = sizeof(changes) / sizeof(int) - 1;
int number;
number = make_change_problem(total_money, changes, kinds_change);
cout << number << endl;
return 0;
}
解法⼆:
// total_money: 要找的零钱总和
// changes: 零钱数组,已经从⼩到⼤排序,第1个元素设为0,有效元素从第2个位置即下标1开始
// kinds_change: 零钱种类
int make_change_problem_v2(int total_money, int *changes, int kinds_change)
{
// opt[i]表⽰i元钱的组合数⽬
std::vector<int> opt(total_money+1, 0);
// 组成0元钱的组合数⽬只有1种,即不选择任何零钱
opt[0] = 1;
// 第⼀个循环计算包含第i种零钱时j元钱的组合数⽬,第⼆个循环计算j(j>=changes[i])元钱的组合数⽬
for (int i = 1; i <= kinds_change; ++i)
{
for (int j = changes[i]; j <= total_money; ++j)
{
opt[j] += opt[j-changes[i]];
}
}
return opt[total_money];
}。

相关文档
最新文档