求解查找假币问题

今天做一下算法课实验三任务一,题目如下:

任务一:求解查找假币问题

有12个硬币,用A-L表示,其中有一个假币,且假币较轻,真币重量相同。每次选择4个硬币放置于天平的左托盘或右托盘进行称重,得到如下结果:

ABCD  EFGH even     //even表示二边一样重,天平平衡

ABCI  EFJK up //up表示前者重,ABCI重量大于EFJK重量,天平不平衡;down表示后者重

ABIJ  EFGH even     //even表示二边一样重,天平平衡

用回溯法实现求解之,并分析其时间复杂度。

 

1.理解

12个硬币分三组,称三次,称重结果题设已给出,根据这三次称重结果利用回溯法设计一个程序找出假币。

 

2.回溯

书上的概念就不搬了,举例说明:玩迷宫游戏,依次尝试可以走的路,此路不同时回到上一个路口继续尝试,最后找到出口。回到上一个路口的过程就是回溯,在算法中借助这种思想尝试求可行解时,遇到不满足条件的情况,回退一步,而不是放弃整个重来,提高了算法效率。看到这里,相信小伙伴们已经明白,我们经常使用的迭代和递归当不满足约束条件而退出当层循环或递归而进行下一层就是回溯,原来只是给这个隐藏的回退过程取了个好听的名字而已。回溯问题的求解过程可以树形结构表示,与DFS类似,但相较DFS有一个回退的过程。

 

3.思路

将12枚硬币依次假设为是假币(重量轻的一个币,题设给出),然后在该币是假币的情况下,将按题设称重方式称重三次的预期结果与题设中称重结果进行比较,相符则该币为假币,违背则回溯,进入下一层循环,即在假设下一个币为假币的情况下进行判断逻辑。如此,便能很轻松的用迭代完成回溯法设计题解程序。

 

4.实现

复制代码
 1 #include<iostream>
 2 #include<string>
 4 using namespace std;
 5 #define N 12
 6 
 7 bool isFake(string lgr[], string rgr[], string res[3], int w[]);
 8 int findFake(string lgr[], string rgr[], string res[3], int w[]);
 9 
10 int main() {
11     //12枚硬币,初始值0
12     int w[N];
13     //三次称重左右天平放置硬币情况,left_group和right_group
14     string lgr[3] = { "ABCD", "ABCI", "ABIJ" };
15     string rgr[3] = { "EFGH", "EFJK", "EFGH" };
16     //三次称重结果
17     string res[3] = { "even", "up", "even" };
18     cout << "假币是:" << (char)('A' + findFake(lgr, rgr, res, w)) << endl;
19     return 0;
20 }
21 
22 bool isFake(string lgr[], string rgr[], string res[], int w[]) {
23     //如果该硬币为假币,我们模拟称重过程,结果应与题设结果一致,返回true,否则返回false
24     for (int i = 0; i < 3; i++) {
25         //天平两边重量
26         int lw = 0, rw = 0;
27         for (unsigned int j = 0; j < lgr[i].size(); j++) {
28             //第一次循环:左"ABCD",右"EFGH"
29             lw += w[lgr[i][j] - 'A'];
30             rw += w[rgr[i][j] - 'A'];
31         }
32         if (lw < rw && res[i] != "down") return false;
33         if (lw == rw && res[i] != "even") return false;
34         if (lw > rw && res[i] != "up") return false;
35     }
36     //如果三次循环结束没返回false即与题设称重结果一致,返回true
37     return true;
38 }
39 
40 int findFake(string lgr[], string rgr[], string res[], int w[]) {
41     for (int i = 0; i < N; i++) {
42         //设第i枚硬币为假币
43         w[i] = -1;
44         if (isFake(lgr, rgr, res, w)) {
45             return i;
46         }
47         //回溯,假设不成立,恢复值。
48         w[i] = 0;
49     }
50     //排除警告 warning C4715: “findFake”: 不是所有的控件路径都返回值
51     return -1;
52 }
复制代码

参考:https://blog.csdn.net/hahadelaochao/article/details/109902128

posted @   一梦两三年13  阅读(609)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示