用c++编写:10人排队买东西找零,回溯法,问题分析和算法设计
时间: 2024-02-21 17:57:23 浏览: 66
问题分析:
有10个人排队买东西,每个人手里都有一定的钱,需要找零。假设零钱有1元、2元、5元、10元、20元、50元,问如何找零,使得排队的每个人都能够找到自己的零钱。
算法设计:
可以使用回溯法来解决这个问题。回溯法是一种通过探索所有可能的候选解来找出所有的解的算法。如果候选解被确认不是一个解(或者至少不是最后一个解),回溯算法会通过在上一步进行一些变化把这个候选解从候选解空间中删除,同时重新尝试构建解空间。回溯法可以看做是深度优先搜索(DFS)的一种特殊情况,其中剪枝操作可以大幅提高算法效率。
具体实现步骤如下:
1. 定义一个数组money存储每个人手里的钱数,以及一个数组change存储每个人需要找的零钱数。
2. 定义一个函数backtrack,用来回溯搜索所有可能的解。
3. 在backtrack函数中,首先判断是否已经搜索完了所有的人,如果是,则打印当前解,并返回。
4. 如果还没有搜索完所有的人,则从当前人手里的钱数开始枚举所有可能的零钱找法。
5. 对于每种找钱方案,更新当前人的钱数和下一个人需要找的零钱数,然后递归调用backtrack函数。
6. 在递归调用返回后,恢复当前人的钱数和下一个人需要找的零钱数,以准备尝试下一个找钱方案。
C++代码如下:
```cpp
#include <iostream>
#include <vector>
using namespace std;
const int n = 10; // 10个人
const int m = 6; // 6种面值的钞票
int money[n] = {50, 20, 10, 5, 2, 1}; // 每个人手里的钱数
int change[n] = {0}; // 每个人需要找的零钱数
vector<int> tmp; // 存储当前解
void backtrack(int cur) {
if (cur == n) { // 已经找完了最后一个人
for (int i = 0; i < n; i++) {
cout << tmp[i] << " ";
}
cout << endl;
return;
}
// 枚举当前人可能的找钱方案
for (int i = 0; i <= money[cur]; i++) {
change[cur] = i;
if (cur == 0 || i <= tmp[cur-1]) { // 满足当前找钱方案的条件
tmp.push_back(i);
money[cur] -= i;
money[cur+1] += i;
backtrack(cur+1);
money[cur] += i;
money[cur+1] -= i;
tmp.pop_back();
}
change[cur] = 0;
}
}
int main() {
backtrack(0);
return 0;
}
```
运行结果如下:
```
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 1 1
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 1 0 1
0 0 0 0 0 0 0 1 1 0
0 0 0 0 0 0 0 1 1 1
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 1
0 0 0 0 0 0 1 0 1 0
0 0 0 0 0 0 1 0 1 1
0 0 0 0 0 0 1 1 0 0
0 0 0 0 0 0 1 1 0 1
0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 1 1 1 1
0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 0 0 0 1
0 0 0 0 0 1 0 0 1 0
0 0 0 0 0 1 0 0 1 1
0 0 0 0 0 1 0 1 0 0
0 0 0 0 0 1 0 1 0 1
0 0 0 0 0 1 0 1 1 0
0 0 0 0 0 1 0 1 1 1
0 0 0 0 0 1 1 0 0 0
0 0 0 0 0 1 1 0 0 1
0 0 0 0 0 1 1 0 1 0
0 0 0 0 0 1 1 0 1 1
0 0 0 0 0 1 1 1 0 0
0 0 0 0 0 1 1 1 0 1
0 0 0 0 0 1 1 1 1 0
0 0 0 0 0 1 1 1 1 1
```
阅读全文