P327. 渔夫捕鱼算法问题

问题描述:

A、B、C、D、E 这5个人合伙夜间捕鱼,凌晨时都已经疲惫不堪,于是各自在河边的树丛中找地方睡着了。第二天日上三竿时,A第一个醒来,他将鱼平分为5份,把多余的一条扔回河中,然后拿着自己的一份回家去了;B第二个醒来,但不知道A已经拿走了一份鱼,于是他将剩下的鱼平分为5份,扔掉多余的一条,然后只拿走了自己的一份;接着C、D、E依次醒来,也都按同样的办法分鱼。

问题:

问这5人至少合伙捕到多少条鱼?

样例

3121

这个问题可以通过逆向推理来解决。我们需要确定这5个人合伙捕到的最少鱼的数量。根据题目描述,每个人在分鱼时都将剩余的鱼平均分为5份,并将多余的鱼扔回河中。以下是解决问题的步骤:

解决思路

  1. 理解分鱼过程:

    • 当A醒来时,他将鱼分为5份,取走1份,多出的1条鱼被扔掉。
    • B醒来时,他在不知道A已经拿走1份的情况下,将剩余的鱼再分成5份,同样扔掉多出的1条。
    • C、D、E也按照同样的方法分鱼。
  2. 逆推每个人的操作:

    • 我们可以从最后一个人E开始推算,逐步计算回去,直到第一个人A。通过这种方法,我们可以求出最少的捕获数量。
  3. 设定变量:

    • 假设在每个人醒来时,剩下的鱼数量为 n。

C

#include <stdio.h>int main() {int n = 1; // 从1条鱼开始while (1) {int fish = n; // 记录当前的鱼的数量// E 醒来fish = (fish - 1) * 4 / 5;if (fish < 0) break;// D 醒来fish = (fish - 1) * 4 / 5;if (fish < 0) break;// C 醒来fish = (fish - 1) * 4 / 5;if (fish < 0) break;// B 醒来fish = (fish - 1) * 4 / 5;if (fish < 0) break;// A 醒来fish = (fish - 1) * 4 / 5;if (fish < 0) break;// 如果最后的fish>=0,更新n并继续查找n++;}printf("%d\n", n - 1); // 输出最后的最小鱼的数量return 0;
}
#include <stdio.h>int main() {int nE = 0; // E 醒来时的鱼数量int nA = 0; // A 醒来时的鱼数量int k = 0;  // k 是某个整数,用于表示 E 的情况// 从最小的 nE 开始,直到找到合适的 nAwhile (1) {nE = 5 * k + 1; // E 的鱼数量公式int nD = nE + 1; // D 醒来时的鱼数量int nC = nD + 1; // C 醒来时的鱼数量int nB = nC + 1; // B 醒来时的鱼数量nA = nB + 1;     // A 醒来时的鱼数量// 检查每个阶段是否符合条件if ((nE - 1) % 5 == 0 && (nD - 1) % 5 == 0 && (nC - 1) % 5 == 0 && (nB - 1) % 5 == 0) {// 如果条件满足,打印 A 醒来时的鱼数量printf("%d\n", nA);break; // 找到合适的数量后退出循环}k++; // 增加 k,尝试下一个可能的数量}return 0;
}

C++

#include <iostream>
using namespace std;int main() {int n = 1; // 从1条鱼开始while (true) {int fish = n; // 记录当前的鱼的数量// E wakes upfish = (fish - 1) * 4 / 5;if (fish < 0) break;// D wakes upfish = (fish - 1) * 4 / 5;if (fish < 0) break;// C wakes upfish = (fish - 1) * 4 / 5;if (fish < 0) break;// B wakes upfish = (fish - 1) * 4 / 5;if (fish < 0) break;// A wakes upfish = (fish - 1) * 4 / 5;if (fish < 0) break;// 如果最后的fish>=0,更新n并继续查找n++;}cout << n - 1 << endl; // 输出最后的最小鱼的数量return 0;
}

上面三个代码都会超时 下面是优化的代码

尝试从初始的鱼的数量开始逐步检查每个渔夫醒来后的鱼的数量。虽然这个方法能得出答案,但由于检查的范围太大,因此可能会导致超时

优化思路

C语言
#include <stdio.h>int main() {int n = 1; // 从1条鱼开始while (1) {int fish = n; // 记录当前的鱼的数量int valid = 1; // 标记当前的鱼数是否有效// 从 A 到 E 依次推导for (int i = 0; i < 5; ++i) {if ((fish - 1) % 5 != 0) { // 如果不能被平分valid = 0; // 该情况不满足break;}fish = (fish - 1) * 4 / 5; // 计算下一个渔夫的鱼数}if (valid) {printf("%d\n", n); // 找到的最小数量break;}n++; // 继续尝试下一个数量}return 0;
}
C++
#include <iostream>
using namespace std;int main() {int n = 1; // 从1条鱼开始while (true) {int fish = n; // 记录当前的鱼的数量bool valid = true; // 标记当前的鱼数是否有效// 从 A 到 E 依次推导for (int i = 0; i < 5; ++i) {if ((fish - 1) % 5 != 0) { // 如果不能被平分valid = false; // 该情况不满足break;}fish = (fish - 1) * 4 / 5; // 计算下一个渔夫的鱼数}if (valid) {cout << n << endl; // 找到的最小数量break;}n++; // 继续尝试下一个数量}return 0;
}
 C语言版本
#include <stdio.h> // 引入标准输入输出库int main() {int x = 0; // 计数器,用于控制循环次数,最大值为6double y = 6, m = 6; // y 初始化为6,m 也初始化为6,y 表示鱼的数量,m 用于存储当前整数值// 进入一个无限循环,直到 x 达到6为止while (x < 6) {// 根据公式 y = y * 1.25 + 1 计算下一个鱼的数量// 这个公式是为了模拟渔夫们分鱼后的数量变化y = y * 1.25 + 1; // 检查 y 是否为整数,如果不是,则 y 的值大于其整数部分if (y > (int)y) { // 如果 y 不是整数,则增加 m 的值m++; // 将 y 设置为 m 的值,使其为下一个整数y = m; // 重置 x 为0,重新开始计数x = 0; }// 增加计数器 x,以便跟踪循环次数x++; }// 打印 y 的值,使用 %.0lf 格式确保输出为整数printf("%.0lf", y); return 0; // 返回0表示程序成功结束
}

正推法

正推是从一个最小的可能值(这里是1条鱼)开始,依次进行计算,直到满足所有渔夫的分鱼条件。

代码解析

  1. 初始化:

    • fish = 1:从1条鱼开始尝试。
  2. 循环:

    • while True:不断尝试增加鱼的数量,直到找到满足条件的数量。
    • total_fish = fish:记录当前的鱼的数量。
  3. 检查条件:

    • 使用一个for循环来模拟5个渔夫的分鱼过程。
    • 在每次循环中:
      • 检查(total_fish - 1) % 5 == 0:这确保了当前剩余鱼数减去1后能被5整除,符合渔夫的分鱼逻辑。
      • 如果条件满足,计算下一个渔夫醒来后的鱼的数量:total_fish = (total_fish - 1) // 5 * 4
      • 如果条件不满足,设置valid = False并跳出循环。
  4. 找到结果:

    • 如果valid保持为True,则返回当前的fish值。
    • 如果不满足条件,则增加鱼的数量并重新进行检查。

正推 vs 反推

  • 正推:从较小的可能数量开始,逐步向上推导,直到找到符合条件的最小数量。
  • 反推:从最终状态出发,逐步推导回去,通常是通过假设每个渔夫醒来时的鱼数和他们的操作来确定初始的鱼数。

在这个问题中,你的代码通过正推方法成功找到满足条件的鱼的数量。

python

def find_minimum_fish():fish = 1  # 初始化鱼的数量,从1条鱼开始尝试while True:  # 无限循环,直到找到满足条件的鱼的数量total_fish = fish  # 将当前鱼的数量赋值给 total_fish,方便后续计算valid = True  # 用于标记当前数量是否满足所有渔夫的分鱼条件# 依次验证5个渔夫for _ in range(5):  # 遍历5个渔夫# 检查当前鱼的数量减去1是否能被5整除if (total_fish - 1) % 5 == 0:  # 如果可以被5整除,计算下一个渔夫醒来后剩下的鱼的数量total_fish = (total_fish - 1) // 5 * 4  # 先减去1条鱼,然后将剩下的鱼数的四分之五赋值给 total_fishelse:valid = False  # 如果不符合条件,设置标记为 Falsebreak  # 跳出循环,不再检查后续的渔夫# 如果 valid 仍然为 True,说明所有渔夫的条件都满足if valid:return fish  # 返回当前鱼的数量,作为结果fish += 1  # 如果当前数量不满足条件,增加鱼的数量并重新开始验证# 运行结果
result = find_minimum_fish()  # 调用函数并获取结果
print(result)  # 打印结果

 C语言

#include <stdio.h>int find_minimum_fish() {int fish = 1; // 从1条鱼开始while (1) {int total_fish = fish; // 记录当前的鱼的数量int valid = 1; // 用于判断是否符合所有渔夫的要求// 依次验证5个渔夫for (int i = 0; i < 5; ++i) {if ((total_fish - 1) % 5 == 0) { // 检查能否被5整除total_fish = (total_fish - 1) * 4 / 5; // 计算下一个渔夫的鱼的数量} else {valid = 0; // 不符合条件break; // 跳出循环}}if (valid) {return fish; // 找到符合条件的鱼的数量}fish++; // 增加鱼的数量并重新检查}
}int main() {int result = find_minimum_fish(); // 调用函数printf("%d\n", result); // 输出结果return 0; // 程序正常结束
}

C++

#include <iostream>
using namespace std;int find_minimum_fish() {int fish = 1; // 从1条鱼开始while (true) {int total_fish = fish; // 记录当前的鱼的数量bool valid = true; // 用于判断是否符合所有渔夫的要求// 依次验证5个渔夫for (int i = 0; i < 5; ++i) {if ((total_fish - 1) % 5 == 0) { // 检查能否被5整除total_fish = (total_fish - 1) * 4 / 5; // 计算下一个渔夫的鱼的数量} else {valid = false; // 不符合条件break; // 跳出循环}}if (valid) {return fish; // 找到符合条件的鱼的数量}fish++; // 增加鱼的数量并重新检查}
}int main() {int result = find_minimum_fish(); // 调用函数cout << result << endl; // 输出结果return 0; // 程序正常结束
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/56035.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【D3.js in Action 3 精译_034】4.1 D3 中的坐标轴的创建(中一)

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一部分 D3.js 基础知识 第一章 D3.js 简介&#xff08;已完结&#xff09; 1.1 何为 D3.js&#xff1f;1.2 D3 生态系统——入门须知1.3 数据可视化最佳实践&#xff08;上&#xff09;1.3 数据可…

FFmpeg的简单使用【Windows】--- 简单的视频混合拼接

实现功能 点击【选择文件】按钮在弹出的对话框中选择多个视频&#xff0c;这些视频就是一会将要混剪的视频素材&#xff0c;点击【开始处理】按钮之后就会开始对视频进行处理&#xff0c;处理完毕之后会将处理后的文件路径返回&#xff0c;并在页面展示处理后的视频。 视频所…

处理Java内存溢出问题(java.lang.OutOfMemoryError):增加JVM堆内存与调优

处理Java内存溢出问题&#xff08;java.lang.OutOfMemoryError&#xff09;&#xff1a;增加JVM堆内存与调优 在进行压力测试时&#xff0c;遇到java.lang.OutOfMemoryError: Java heap space错误或者nginx报错no live upstreams while connecting to upstream通常意味着应用的…

[Hbase]一 HBase基础

1. HBase简介 1.1 HBase定义 HBase数据模型的关键在于 稀疏、分布式、多维、排序 的映射。其中映射 map指代非关系型数据库的 key-Value结构。 1.2 HBase数据模型 1)Name Space 命名空间,类似于关系型数据库的database 概念,每个命名空间下有多个表。HBase 两个自…

鸿蒙NEXT开发-知乎评论小案例(基于最新api12稳定版)

注意&#xff1a;博主有个鸿蒙专栏&#xff0c;里面从上到下有关于鸿蒙next的教学文档&#xff0c;大家感兴趣可以学习下 如果大家觉得博主文章写的好的话&#xff0c;可以点下关注&#xff0c;博主会一直更新鸿蒙next相关知识 专栏地址: https://blog.csdn.net/qq_56760790/…

【C++】--内存管理

&#x1f47e;个人主页: 起名字真南 &#x1f47b;个人专栏:【数据结构初阶】 【C语言】 【C】 目录 1 C/C内存分布2 C语言中动态内存管理方式 &#xff1a;3 C内存管理方式3.1 new/delete操作内置类型3.2 new和delete操作自定义类型 4 operator new与operator delete4.1 opera…

SwiftUI 在 iOS 18 中的 ForEach 点击手势逻辑发生改变的解决

概述 原本在 iOS 17 中运行良好的 SwiftUI 代码突然在 iOS 18 无法正常工作了&#xff0c;具体表现为原来视图中的的点击手势无法响应。 这是怎么回事呢&#xff1f; 且看分解&#xff01;Let’s go&#xff01;&#xff01;&#xff01;&#x1f609; 问题现象 从下面的演示…

图书馆自习室座位预约管理微信小程序+ssm(lw+演示+源码+运行)

摘 要 随着电子商务快速发展世界各地区,各个高校对图书馆也起来越重视.图书馆代表着一间学校或者地区的文化标志&#xff0c;因为图书馆丰富的图书资源能够带给我们重要的信息资源&#xff0c;图书馆管理系统是学校管理机制重要的一环&#xff0c;,面对这一世界性的新动向和新…

Docker-nginx数据卷挂载

数据卷&#xff08;volume&#xff09;是一个虚拟目录&#xff0c;是容器内目录与宿主机目录之间映射的桥梁。 以Nginx为例&#xff0c;我们知道Nginx中有两个关键的目录&#xff1a; html&#xff1a;放置一些静态资源conf&#xff1a;放置配置文件 如果我们要让Nginx代理我们…

磁盘存储链式结构——B树与B+树

红黑树处理数据都是在内存中&#xff0c;考虑的都是内存中的运算时间复杂度。如果我们要操作的数据集非常大&#xff0c;大到内存已经没办法处理了该怎么办呢&#xff1f; 试想一下&#xff0c;为了要在一个拥有几十万个文件的磁盘中查找一个文本文件&#xff0c;设计的…

Dockerfile 详解

Dockerfile是自定义Docker镜像的一套规则&#xff0c;由多条指令构成&#xff0c;每条指令都会对应于Docker镜像中的每一层&#xff0c;因为Docker是分层存储的。以下是Dockerfile中各个参数的详解及演示解析&#xff1a; 1. FROM 功能&#xff1a;指定待扩展的父级镜像&#…

sass学习笔记(1.0)

1.使用变量 sass可以像声明变量那样进行使用&#xff0c;这样同样的样式&#xff0c;就可以使用相同的变量来提高复用。 语法为&#xff1a;$ 变量名 在界面中也可以正常的显示 当然了&#xff0c;变量之间也可以相互引用&#xff0c;比如下面 div{$_color: #d45387;$BgColo…

用C++编写信息管理系统(歌单信息管理)

C语言是面向过程的编程语言&#xff0c;而C是面向对象的编程语言&#xff0c;在书写代码时风格有所不同&#xff08;也存在很多共性&#xff09;。 程序说明 本次系统程序使用的是C语言进行编写&#xff0c;主要考虑怎么实现面向对象的问题。 因为本次程序属于小型系统程序&…

多元线性回归:机器学习中的经典模型探讨

引言 多元线性回归是统计学和机器学习中广泛应用的一种回归分析方法。它通过分析多个自变量与因变量之间的关系&#xff0c;帮助我们理解和预测数据的行为。本文将深入探讨多元线性回归的理论背景、数学原理、模型构建、技术细节及其实际应用。 一、多元线性回归的背景与发展…

2024免费mac苹果电脑清理垃圾软件CleanMyMac X4.15.8

对于苹果电脑用户来说&#xff0c;设备上积累的垃圾文件可能会导致存储空间变得紧张&#xff0c;影响电脑的性能和使用体验。尤其是那些经常下载和安装新应用、编辑视频或处理大量照片的用户&#xff0c;更容易感受到存储空间的压力。面对这种情况&#xff0c;寻找一种有效的苹…

计组_中断响应的步骤

2024.10.13&#xff1a;计算机组成原理学习笔记 中断响应步骤 中断响应 &#xff08;中断响应的过程也称中断隐指令&#xff09;第一步&#xff1a;关中断第二步&#xff1a;保存断点第三步&#xff1a;引出中断服务程序中断源识别判优方法1&#xff1a;软件查询方法中断源识别…

74.【C语言】文件操作(1)

目录 1.进行文件操作的原因 销毁的示例 2.文件的类型 1.操作文件的步骤 2.文件名 3.查看文件路径的方法 方法1 方法2 方法3 4.数据文件的介绍 举例 ① ASCII码的形式(即字符形式)存储 ②二进制形式存储 理解"不加转换"的含义 1.进行文件操作的原因 为…

maven加载依赖成功但是引入import不了包,注解报错

突然就复现不出来了&#xff0c;奇了怪了&#xff0c;简单说一下吧&#xff0c;就是模块里引入了SpringBoot Test那个依赖然后&#xff0c; 这个地方是显示引入成功的&#xff0c;但是 这个包下没有&#xff0c;导致我SpringBootTest一直出不来&#xff0c;就找不到这个包下的注…

Qt事件——鼠标事件

通过label来显示各种事件 鼠标按下事件 //按下显示坐标 void MyLabel::mousePressEvent(QMouseEvent * ev) {int i ev->x();int j ev->y();//判断按下的鼠标键位if (ev->button() Qt::LeftButton) {qDebug() << "LeftButton";}else if (ev->bu…