P327. 渔夫捕鱼算法问题

news2024/10/23 23:23:45

问题描述:

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 开始,直到找到合适的 nA
    while (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 up
        fish = (fish - 1) * 4 / 5;
        if (fish < 0) break;

        // D wakes up
        fish = (fish - 1) * 4 / 5;
        if (fish < 0) break;

        // C wakes up
        fish = (fish - 1) * 4 / 5;
        if (fish < 0) break;

        // B wakes up
        fish = (fish - 1) * 4 / 5;
        if (fish < 0) break;

        // A wakes up
        fish = (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; // 计数器,用于控制循环次数,最大值为6
    double 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_fish
            else:
                valid = False  # 如果不符合条件,设置标记为 False
                break  # 跳出循环,不再检查后续的渔夫
        
        # 如果 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.coloradmin.cn/o/2213087.html

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

相关文章

雷池社区版如何使用静态资源的方式建立站点

介绍&#xff1a; SafeLine&#xff0c;中文名 “雷池”&#xff0c;是一款简单好用, 效果突出的 Web 应用防火墙(WAF)&#xff0c;可以保护 Web 服务不受黑客攻击。 雷池通过过滤和监控 Web 应用与互联网之间的 HTTP 流量来保护 Web 服务。可以保护 Web 服务免受 SQL 注入、X…

Mac 窗口切换技巧:大幅提高效率的必备指南

在日常使用 Mac 电脑的过程中&#xff0c;高效地切换窗口可以极大地提升工作效率。无论是在多个文档之间快速切换&#xff0c;还是在不同的应用程序之间自如跳转&#xff0c;掌握一些实用的窗口切换技巧能让你的操作如鱼得水。下面就为大家详细介绍一些 Mac 窗口切换的技巧。 …

[Linux] 逐层深入理解文件系统 (2)—— 文件重定向

标题&#xff1a;[Linux] 逐层深入理解文件系统 &#xff08;2&#xff09;—— 文件重定向 个人主页水墨不写bug &#xff08;图片来源于网络&#xff09; 目录 一、文件的读取和写入 二、文件重定向的本质 1.手动模拟重定向的过程——把标准输出重定向到redir.txt 2.重定向…

支付宝开放平台-开发者社区——AI 日报「10 月 14 日」

1 大模型「强崩溃」&#xff01;Meta新作&#xff1a;合成数据有「剧毒」&#xff0c;1%即成LLM杀手 新智元&#xff5c;阅读原文 1%合成数据&#xff0c;就能让模型瞬间崩溃&#xff01;甚至&#xff0c;参数规模越大&#xff0c;模型崩溃越严重。Nature封面一篇论文证实&am…

Acwing 前缀与差分

1.一维前缀和 一维前缀和&#xff1a;S[i]a1a2a3a4…ai&#xff0c;要求a从a1开始&#xff0c;且S[0]0 前缀和的作用&#xff1a;给定一组序列数据&#xff0c;可以计算任意第l个数到第r个数的和&#xff0c;S[r]-S[l-1]&#xff08;这里就解释了为什么要求S[0]0&#xff0c;因…

电力电子技术(一)

变压器漏感对整流电路的影响&#xff1a;

Find My微型电磨机|苹果Find My技术与电磨机结合,智能防丢,全球定位

微型电磨机是一种多功能电动工具&#xff0c;主要用于打磨、抛光、雕刻、钻孔等多种作业。‌ 它由控制箱和电磨笔两部分组成&#xff0c;通过直流稳压电源供电&#xff0c;电磨笔以直流马达为驱动源&#xff0c;带动磨头进行高速旋转机械运动&#xff0c;配合不同材质、形状的磨…

制药企业MES与TMS的数据库改造如何兼顾安全与效率双提升

*本图由AI生成 在全球制造业加速数字化转型的浪潮中&#xff0c;一家来自中国的、年营业额超过200亿元的制药企业以其前瞻性的视角和果断的行动&#xff0c;成为该行业里进行国产化改造的先锋。通过实施数据库改造试点项目&#xff0c;该企业实现了其关键业务系统MES&#xff0…

请求的响应----状态码分为五大类(爬虫)

前言 一个爬虫的成功与否&#xff0c;在于你是否拿到了想要的数据&#xff1b;一个请求的成功与否&#xff0c;在于响应的状态码&#xff0c;它标明了当前请求下这个响应的结果&#xff0c;是好还是坏。上节课程学习了HTTPS和HTTP协议的各自优势&#xff0c;本节课程进入到请求…

C++: AVL树的实现

一.AVL树的旋转 AVL树是平衡搜索二叉树的一种。 平衡因子&#xff1a;节点右树的高度减左树的高度&#xff0c;AVL树规定平衡因子的绝对值小于2。若不在这个范围内&#xff0c;说明该树不平衡。 AVL树节点&#xff1a; struct AVLTreeNode {AVLTreeNode(const T& data …

【AI 新观察】“转人工!转人工!”——智能客服痛点与破局之路

在当今数字化时代&#xff0c;智能客服在电商等众多领域被广泛应用&#xff0c;然而&#xff0c;一句又一句“转人工&#xff01;转人工&#xff01;”却常常暴露出智能客服存在的痛点。一、智能客服之痛 1. 理解偏差引不满 智能客服在理解客户问题时&#xff0c;常常出现偏差…

代码随想录 -- 回溯 -- 解数独

37. 解数独 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; class Solution(object):def back(self,board):for i in range(len(board)):for j in range(len(board[0])):if board[i][j] ! .:continuefor k in range(1,10):if self.isValid(i,j,k,board):board[i][j…

为什么要做自动化测试

一、自动化测试 自动化测试是把以人为驱动的测试行为转化为机器执行的一种过程。 个人认为&#xff0c;只要能服务于测试工作&#xff0c;能够帮助我们提升工作效率的&#xff0c;不管是所谓的自动化工具&#xff0c;还是简单的SQL 脚本、批处理脚本&#xff0c;还是自己编写…

10.13论文阅读

通过联合学习检测和描述关键点增强可变形局部特征 摘要 局部特征提取是计算机视觉中处理图像匹配和检索等关键任务的常用方法。大多数方法的核心理念是图像经历仿射变换&#xff0c;忽略了诸如非刚性形变等更复杂的效果。此外&#xff0c;针对非刚性对应的新兴工作仍然依赖于…

2024 年江苏省职业院校技能大赛“区块链技术应用” 赛项赛卷(样卷)运维题解析二

运维题 环境: ubuntu20 fisco 2.8.0 前言 准备两台机子,并且可以能相互pin通 192.168.19.133 [M1-A] 192.168.19.137 [M2-B] 子任务 1-2-3:区块链节点运维 基于已搭建的区块链系统与控制台,在机器(M1-A)上开展区块链群组与 节点的运维工作,具体内容如下: (1)基于…

Jenkins如何更改主目录文件夹?设置路径?

Jenkins如何更改主目录文件夹&#xff1f;设置路径&#xff1f;?简单几步&#xff0c;让你轻松解决。 工具/原料 联网电脑 方法/步骤 1. ssh连接到jenkins的服务器。使用root权限执行下面的命令&#xff0c;第一句是查看jenkins是否启用&#xff0c;启用的话需要第二个命令关…

肽合同制造(CDMO):北美和欧洲是全球最大肽合同制造(CDMO)消费地区

据 HengCe 最新调研&#xff0c;2023年中国肽合同制造&#xff08;CDMO&#xff09;市场销售收入达到了 万元&#xff0c;预计2030年可以达到 万元&#xff0c;2024-2030期间年复合增长率(CAGR)为 %。本研究项目旨在梳理肽合同制造&#xff08;CDMO&#xff09;领域产品系列&am…

【linux开发-驱动】-linux内核相关

开发板&#xff1a;STM32MP157 一、编译linux内核源码 编译完成以后就会在 arch/arm/boot 这个目录下生成一个叫做 uImage 的文件&#xff0c;uImage 就是 我们要用的 Linux 镜像文件。 Linux 编 译 的 时 候 需 要 设 置 目 标 板 架 构 ARCH 和 交 叉 编 译 器 CROSS_COMP…

确认:代码覆盖率是无用的管理指标

发现拆解代码覆盖率指标的简单证明 代码覆盖率是衡量软件产品质量的一个强有力的指标&#xff0c;多年来&#xff0c;技术领导者们对此深信不疑。从表面上看&#xff0c;其理由似乎很充分&#xff1a;测试越彻底&#xff0c;代码覆盖率就越高&#xff0c;因此&#xff0c;我们…

数据屏蔽与加密:代理用户需要了解的内容

您可能已经意识到数据安全和隐私的重要性。尽管存在各种方法来解决这两个问题&#xff1a;道德考量和监管要求&#xff0c;在本指南中&#xff0c;我们将重点介绍两种流行的策略&#xff1a;屏蔽和加密 - 以及它们的比较。 那么&#xff0c;哪个方法更胜一筹呢&#xff1f;答案…