数据结构与算法笔记:计算思维之经典农夫过河问题C++实现

2023-10-26

农夫、羊、狼、菜的过河问题

问题描述

  • 角色:农夫,羊,狼,菜
  • 条件1:船很小,只能装下农夫和其他一个角色
  • 条件2:无人看管,羊吃菜,狼吃羊
  • 问:如何让其他三种角色被农夫平安带着过河?

相关分析

  • 我们可以先用人脑尝试一下相关渡河策略
    • 1 ) 先渡狼,人回来再渡菜,人回来再渡羊
    • 2 ) 先渡菜,人回来再渡狼,人回来再渡羊
    • 以上两种很好想到,而且我们可以知道羊这种角色是不能先渡河过去的,羊需要最后再渡
    • 如果先渡了羊了,之后再渡任何其他角色,都要将羊带回来
    • 可以参考小游戏:http://gameschool.cc/game/178 自己尝试一下
  • 我们需要让计算机来计算出来可行的方案
    • 使用策略:枚举
    • 相关算法设计
      • 解决问题的算法有很多种,这里仅提供一种
      • 将此问题抽象为状态和行为的变化
      • 以渡河与否作为判断状态条件
      • 未渡河(在河岸的一侧)状态:0,行为:0
      • 渡河(到河岸的另一侧)状态:1,行为:1
      • 算法是切换各个角色的渡河与未渡河状态进行枚举,得到最终结果(一种可行的方案)

算法实现

#include <cstdio>
#include <cassert>
#include <cstring>

// 状态值只有两种 0, 1
struct  State {
    int h; // 人 human
    int w; // 狼 wolf
    int s; // 羊 sheep
    int v; // 菜 vegetable
};

// 渡河函数
State pass(State s, char role) {
    // 切换人的状态
    s.h =  1 - s.h;
    if(role == '-') {
        // do nothing
    } else if(role == 'W') {
        // 渡狼 切换狼的状态
        s.w = 1 - s.w;
    } else if(role == 'S') {
        // 渡羊 切换羊的状态
        s.s = 1 - s.s;
    } else if(role == 'V') {
        // 渡菜 切换菜的状态
        s.v = 1 - s.v;
    } else {
        // 直接崩溃,方便调试
        assert(0);
    }
    return s;
};

// 标记已尝试的策略
bool passed[2][2][2][2];

// 检测状态是否合法
bool invalid_state_check(State s) {
    // 人和羊不在一边,且羊和狼在一起
    if(s.h != s.s && s.s == s.w) return true;
    // 人和羊不在一边,且羊和菜在一起
    if(s.h != s.s && s.s == s.v) return true;
    return false;
};

// 检测是否为最终状态
bool final_state_check(State s) {
    // 最终状态为:人,狼,羊,菜都已渡河
    if(s.h == 1 && s.w == 1 && s.s == 1 && s.v == 1) return true;
    return false;
};

// 结果集 开辟一个较大的空间
char result[1000];

// 打印结果
void print_result(int step) {
    for(int i = 0; i < step; i++) {
        if(i != 0) {
            printf(" ");
        }
        printf("H");
        if(result[i] != '-') {
            printf("%c", result[i]);
        }
    }
   puts("");
};

// 开始尝试 false 停止
bool go(State s, int step) {
	// 调试输出
    // printf("%d %d %d %d\n", s.h, s.w, s.s, s.v);
    // 判断是否合法
    if(invalid_state_check(s)) {
        return false;
    };

    // 判断是否最终
    if(final_state_check(s)) {
        // 打印结果
        print_result(step);
        return true;
    };

    // 判断是否已经尝试
    if(passed[s.h][s.w][s.s][s.v]) {
        return false;
    };

    // 标记已尝试策略
    passed[s.h][s.w][s.s][s.v] = true;

    // 处理下一个状态 next state
    State ns;
    ns = pass(s, '-');
    result[step] = '-';
    if(go(ns, step+1)) return true;

    // 渡狼
    if(s.h == s.w) {
        result[step] = 'W';
        ns = pass(s, 'W');
        if(go(ns, step+1)) return true;
    };
    
    // 渡羊
    if(s.h == s.s) {
        result[step] = 'S';
        ns = pass(s, 'S');
        if(go(ns, step+1)) return true;
    };
    
    // 渡菜
    if(s.h == s.v) {
        result[step] = 'V';
        ns = pass(s, 'V');
        if(go(ns, step+1)) return true;
    };

    return false;
};

// main函数
int main() {
    memset(passed, 0, sizeof(passed));
    State init_state = {0, 0, 0, 0};
    go(init_state, 0);
    return 0;
};

最终结果

  • 输出:HS H HW HS HV H HS
  • 解释:先渡羊,人单独回来,再渡狼,人带着羊回来,再渡菜,人回来,最后渡羊
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构与算法笔记:计算思维之经典农夫过河问题C++实现 的相关文章

  • IUnknown—COM和MFC

    转自 http hi baidu com zhangqiuxi blog item 6d9603ad9c8fe5084b36d6a0 html 问题 我用MFC编写COM程序有一段时间了 知道如何使用宏和嵌套类 以及如何在嵌套类中处理IUn
  • SQL 查询指定行数的数据。

    今天遇到一个关于 查询指定行数的数据 的sql查询语句问题 突然发现以前没怎么接触过 刚才想起来了 赶紧看了下文档 又上网搜了下 有了下面的东西 不知道有没有什么地方不对 oracle 先看一下文档中关于any和all的例子 很不错噢 An
  • Qt5学习之路(vs2012下创建一个QT应用程序)2013-10-14

    刚开始学习QT在网上找的资料基本都是使用QT Create进行开发的 VS下开发的学习资料感觉很少很难找的到 视频教程也基本没看到过貌似 因为我们研发中心是使用MFC进行开发开发工具是VS2010 使用QT开发的话基本我们不会再使用QT C
  • 解决“17: 错误:程序中有游离的‘\240’,\302’

    参考链接 https blog csdn net asuphy article details 54602426 执行如下命令即可 sed i s o240 o302 g dy haikang test cpp
  • std::nth_element bug引起的crash问题

    1 源码 auto less compare const MirroringGroup mg1 const MirroringGroup mg2 gt bool return mg1 usage lt mg2 usage std nth e
  • 简析多级指针解引用

    转自 简析多级指针解引用 指针是C语言中公认的最为强大的语法要素 但同时也是最难理解的语法要素 它曾给程序员带来了无数麻烦和痛苦 以致于在C语言之后诞生的很多新兴 语言中我们再也难觅指针的身影了 下面是一个最简单的C语言指针的例子 int
  • C/C++中浮点数格式学习——以IEEE75432位单精度为例

    这是浮点数的通常表示形式 在IEEE754中 单精度浮点数有如下形式 32位单精度 单精度二进制小数 使用32个比特存储 1 8 23位长 S Exp Fraction 31 30至23偏正值 实际的指数大小 127 22至0位编号 从右边
  • 互联网创业盈利模式指南

    看了很多创业的case 都有点下笔千言 离题万里的 情况 就是很多case都很精彩 但是公司 的价值最终是落实到 给创业者和投资人的回报的 因此 所有的case 最终都是 落实到盈利 模式上 一位投资人士说的很明确 中国的盈利模式很简单 就
  • 为何在新建STM工程中全局声明两个宏

    在uVision中新建STM32工程后 需要从STM32标准库中拷贝标准外设驱动到自己的工程目录中 此时需要在工程设置 gt C C 选项卡下的Define文本框中键入这两个全局宏定义 STM32F40 41xxx USE STDPERIP
  • Trace Function Enter, Exit and Leave

    http developer nokia com community wiki Trace Function Enter Exit and Leave
  • Dev-C++之开启装逼效果

    Dev C 是个不错的C IDE 在10年前 它是很不错 在现在 它是个以界面丑陋和调试像吃粑粑这两点著称 如下图 实在是丑到离谱 丑到无法忍受 可是没办法呀 人家CCF规定比赛用这个 你个小蒟蒻吵什么 我现在就来讲讲怎么把你的Dev C
  • 在聚会中常玩数七的游戏,七的倍数和带有七的数字都不能说,比如14,27,28。请找出1~100的不能说的数字。...

    利用ES5的filter高阶函数来实现 var arr 1 2 3 4 5 6 7 17 27 21 22 28 100 r arr filter function x return x 10 7 x 7 0 alert r 7 14 17
  • 【C/C++】 - Linux下查找函数头文件 以及 man命令拓展

    背景 比如现在需要找C语言 sleep函数的头文件 使用man来查找 可以先man sleep 可以发现出来的默认是sleep 1 是一个User Commands 明显不是我们需要的 这里提示了 看sleep 3 那我们查看下sleep
  • visual studio 一直显示正在准备解决方案

    首先重启电脑 无法解决的情况下执行以下步骤 Kill Visual Studio Open Visual Studio without loading a solution Disable AnkhSvn as Source Control
  • 检查内存泄露

    自己编写的视频处理程序出现了一个问题 每帧的运行时间随着运行时间在不断增长 很大可能是出现了内存泄露 于是学习了一些查看内存泄露的方法 做了两种尝试 一是VS自带的DEBUG下的检测 view pl html view plain copy
  • 如何生成有效的 ECDSA EC 密钥对?

    我正在尝试在 Android 中使用 SpongyCastle 生成 ECDSA 密钥对 这是代码 static Security insertProviderAt new org spongycastle jce provider Bou
  • enable_shared_from_this使用介绍

    文章目录 enable shared from this定义 使用场合 源码实现 注意 enable shared from this定义 定义于头文件 template lt class T gt class enable shared
  • C 语言教程:数据类型和格式说明符

    C 语言中的数据类型 C 中的变量必须是指定的 数据类型 并且您必须在 printf 函数中使用 格式说明符 来显示它 创建变量 int myNum 5 整数 没有小数点 float myFloatNum 5 99 浮点数 char myL
  • C++中的并发多线程网络通讯

    C 中的并发多线程网络通讯 一 引言 C 作为一种高效且功能强大的编程语言 为开发者提供了多种工具来处理多线程和网络通信 多线程编程允许多个任务同时执行 而网络通信则是现代应用程序的基石 本文将深入探讨如何使用C 实现并发多线程网络通信 并
  • C 语言文件读取全指南:打开、读取、逐行输出

    C 语言中的文件读取 要从文件读取 可以使用 r 模式 FILE fptr 以读取模式打开文件 fptr fopen filename txt r 这将使 filename txt 打开以进行读取 在 C 中读取文件需要一点工作 坚持住 我

随机推荐

  • 浅谈 防抖和节流

    防抖和节流 是优化高频率执行代码的手段 目的 节约浏览器 服务器的性能 主要方式 减少函数执行的次数 函数防抖 debounce 函数防抖 事件被触发 等待n秒后再执行回调 如果在这n秒内又被触发 则重新计数 防抖的目的 目的是为了让一定时
  • pybind 回调 多线程 异常

    thread代码 int RecvThread SOCKET sockClient py function caminfocall g caminfocall caminfocall py function caminfocall py f
  • quickjs集成mfc的实现

    QuickJS是一个轻量级的JavaScript解释器 可以在各种平台上运行 如果你想在MFC应用程序中使用QuickJS 你可以使用以下方法来实现 下载QuickJS源代码 然后在MFC应用程序中包含QuickJS文件 在MFC应用程序中
  • 操作系统笔记整理 ——目录索引页

    操作系统笔记整理 目录索引页 笔记整理参考书籍 计算机操作系统 第四版 汤小丹等编著 以下笔记整理主要包含了前八章的内容 具体包含的内容会在下面详细说明 笔记尚有许多不足之处 如果大家发现错误还请私信我修改 感谢 目录即链接 点击目录即可跳
  • XML:你真的有必要了解一下我

    对XML的深入浅出 一 概念 二 功能 三 基本语法 四 快速入门 五 组成部分 5 1文档声明 六 约束 6 1 DTD 6 2 Schema 七 解析 7 1 解析XML的方式 7 2常见解析器 八 Jsoup详解 8 1 快速入门 8
  • 第一届全国技能大赛(世赛项目)河北省选拔赛 网络安全项目任务书

    第一届全国技能大赛 世赛项目 河北省选拔赛 网络安全项目任务书 模块A 网络基础构建 网络基础服务搭建 1 第一部分 网络基础构建 2 第二部分 网络基础服务搭建 模块B 网络安全事件响应 数字取证调查和应用程序安全 1 第一部分 网络安全
  • 流程制造行业MES系统的四大应用特点

    MES制造执行系统就是生产加工过程执行系统 该系统可以融合生产规划信息内容及物料 供应 采购和库存等生产现场管理信息内容 根据数据采集系统 然后融合加工过程中的物料 工时 机器设备 人员等信息内容 让生产管理人员对加工过程及进度 建立一个及
  • 如何利用int型变量存放ip值(c语言)

    IP地址 ip地址是一个32位的二进制数 实际上是4个字节 点分十进制表示为 a b c d a b c d的值都是 0 255 例如ip地址 192 168 0 1 就是一个合格ip地址 可以知道a b c d这些字段都是一个无符号字节表
  • 关于前端文件上传后将文件保存至服务器路径存储在数据库并在相应页面展示的总结

    前期准备 1 开发环境及框架的搭建 基于SSH开发框架 2 数据库建表 表应该有一个字段用来存储文件在服务区上的存储路径 3 map xml文件 4 Action xml文件 5 写好实体类及get set 方法 6 DAO层 7 Acti
  • 线性代数(3)—— 逆矩阵、伴随矩阵、初等矩阵

    参考 张宇高等数学基础30讲 文章目录 1 矩阵的逆 1 1 逆矩阵的定义 1 2 逆矩阵性质与重要公式 1 3 用定义求逆矩阵 1 4 例题 2 伴随矩阵 2 1 伴随矩阵的定义 2 2 伴随矩阵的定义与重要公式 2 3 用伴随矩阵求逆矩
  • 每日一题 LCP 06. 拿硬币

    难度 简单 简单题 不多说 class Solution def minCount self coins List int gt int res 0 for coin in coins res ceil coin 2 return res
  • 国内主要大数据平台比较

    在当前信息时代 大数据处理和分析变得越来越重要 国内涌现了许多主流的大数据平台 它们提供各种功能和工具 帮助企业和组织处理和分析海量数据 本文将比较几个主要的国内大数据平台 并提供相应的源代码示例 阿里云大数据平台 阿里云大数据平台是国内领
  • [JSP暑假实训] 四.MyEclipse+Servlet+JSP实现火车票网站查询、修改、删除操作

    本系列文章是作者暑假给学生进行实训分享的笔记 主要介绍MyEclipse环境下JSP网站开发 包括JAVA基础 网页布局 数据库基础 Servlet 前端后台数据库交互 DAO等知识 前一篇文章讲解了通过Servlet获取所提交的数据 这篇
  • OSB:Rest、Soap、SoapDB接口开发学习

    OSB Rest Soap DBSoap接口开发 开发配置 1 开启服务 2 登录WebLogic Server管理控制台 3 启动osb服务 4 登录ServiceBus控制台 Rest接口的开发 1 测试接口是否可以调通 2 开发接口
  • python opencv 调用摄像头失败问题的解决 Windows

    省流 内含 Python Opencv 双目相机拍照代码 手动 or 自动 可自取 如果你的 cv2 VideoCapture 函数卡住但不报错 打开 Windows 相机 应用可以正常看到摄像头画面 且能够正常用 cv2 imshow 打
  • python flask api接口开发编程

    使用 Python 和 Flask 设计 RESTful API 近些年来 REST REpresentational State Transfer 已经变成了 web services 和 web APIs 的标配 在本文中我将向你展示如
  • 简述同步和异步的区别

    同步是阻塞模式 异步是非阻塞模式 同步就是指一个进程在执行某个请求的时候 若该请求需要一段时间才能返 回信息 那么这个进程将会一直等待下去 直到收到返回信息才继续执行下去 异步是指进程不需要一直等下去 而是继续执行下面的操作 不管其他进程的
  • do-while(0)语句到底有什么用?

    前言 在一个群里面看到一个人问 do while 0 语句有什么用 do while 0 这个程序最终结果不应该就是程序只跑一次 那么写和不写有什么区别呢 do while 0 在复杂宏定义上的优点 为什么需要复杂宏 1 在讲解do whi
  • 反射的补充

    反射可以绕过编译阶段为集合添加数据 反射是作用在运行时的技术 此时集合的泛型将不能产生约束了 此时可以为集合存入其他任意类型的元素 泛型只是在编译阶段可以约束集合只能操作某种数据类型 在编译成Class文件进入运行阶段时 其真实类型都是Ar
  • 数据结构与算法笔记:计算思维之经典农夫过河问题C++实现

    农夫 羊 狼 菜的过河问题 问题描述 角色 农夫 羊 狼 菜 条件1 船很小 只能装下农夫和其他一个角色 条件2 无人看管 羊吃菜 狼吃羊 问 如何让其他三种角色被农夫平安带着过河 相关分析 我们可以先用人脑尝试一下相关渡河策略 1 先渡狼