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;并在页面展示处理后的视频。 视频所…

Vue.js 组件开发详解

在现代前端开发中&#xff0c;Vue.js 是一款非常流行的框架&#xff0c;以其简洁的 API 和灵活的组件化体系深受开发者喜爱。在 Vue.js 中&#xff0c;组件&#xff08;Component&#xff09;是核心概念之一&#xff0c;帮助开发者构建复杂而高效的用户界面。本文将详细讲解 Vu…

处理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…

数据分析库Pandas

一、认识Pandas数据分析库 Pandas是一个功能强大的数据分析库&#xff0c;它提供了丰富的数据结构和函数来处理和分析表格数据。在处理类似您提供的Excel文件时&#xff0c;首先需要导入Pandas库并读取数据&#xff0c;然后进行数据清洗和预处理&#xff0c;最后进行数据分析和…

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

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

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

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

【SQL】深入了解 SQL 索引:数据库性能优化的利器

目录 引言1. 什么是 SQL 索引&#xff1f;1.1 索引的基本概念1.2 索引的优缺点 2. 索引的工作原理2.1 B 树索引2.2 哈希索引2.3 全文索引 3. 索引创建方式3.1 单列索引示意图3.2 复合索引示意图3.3 唯一索引示意图 4. 如何创建索引4.1 创建单列索引4.2 创建唯一索引4.3 创建全文…

在ES6中,数组新增扩展及其用法汇总

在ES6中&#xff0c;数组新增了多项扩展&#xff0c;极大提高了操作数组的便捷性。以下是一些常用的扩展及其用法&#xff1a; 1. Array.from() 用于从类数组对象或迭代器创建一个新的数组实例。这个方法可以接受两个参数&#xff1a; source (来源)&#xff1a;这是必须的参…

Docker-nginx数据卷挂载

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

vue3.2实现AES加密解密,秘钥通过API获取,并混淆秘钥,后端thinkphp

aes.ts文件 import CryptoJS from "crypto-js"; import axios from "axios";export const encrypt async(data: any) > {let storeKey sessionStorage.getItem(a)let storeIv:any sessionStorage.getItem(i)// 如果秘钥或 IV 不存在&#xff0c;尝试…

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

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

Dockerfile 详解

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

Lumerical脚本语言——材料数据库(Material database)

下面的命令用来在材料数据库添加或者拷贝材料&#xff0c;以及设置材料属性&#xff0c;并在任何频率验证给定材料所得到的复反射率。&#xff08;通过简单地对反射率开方就可以得到介电常数&#xff09;。本部分同 INTERCONNECT 不相关。 命令描述 addmaterial 向材料数据库添…

在 Linux 系统中设置 Service 服务开机自启的详细指南

目录 在 Linux 系统中设置 Service 服务开机自启的详细指南一、Linux 服务管理概述二、systemd 中设置服务开机自启2.1 systemd 介绍2.2 如何检查服务的状态2.3 启用服务开机自启2.4 手动启动和停止服务2.5 检查服务是否成功启用2.6 禁用开机自启服务 三、在 sysvinit 中设置服…

sass学习笔记(1.0)

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

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

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