【算法设计与分析】六、动态规划:(二)上机-1、地牢逃生【理论到程序】

文章目录

  • 一、题目
    • 1、问题
    • 2、输入输出要求
    • 3、样例说明
    • 4、数据范围
  • 二、思路
    • 1、GPT4 - fail
      • 算法解释
      • C++ 实现
    • 2、Claude3 - fail
      • 问题分析
      • 算法实现
    • 3、个人拙见 - succeed
  • 三、代码实现

一、题目

1、问题

  用一个 n×n 的矩阵表示一座地牢,矩阵中第 i 行第 j 列的方格的值表示位置 (i,j) 的地势高度 h(i,j)。
  时间 T=0 的时刻地牢开始下雨,当时间 T=t 时,地牢任意位置的水位都等于t 。任意时刻可以从当前位置游向上下左右四周相邻的任意一个位置,但是游动的前提是:此时水位必须淹没这个位置和其相邻位置,即如果在 T=t 时想从 (i,j) 位置移动到 (i,j+1) 位置,需要满足t≥h(i,j),t≥h(i,j+1) 。假定在方格内部游动不耗时。 时间 T 的取值是正整数。
  求:从 (1,1) 位置出发,最少耗时多久可以到达 (n,n) 。

2、输入输出要求

  • 输入格式
    • 第一行一个整数 n 。
    • 接下来 n 行,每行 n 个整数,代表 h(i,j) 。
  • 输出格式
    • 输出一个整数,表示最少耗时。
  • 输入样例
2
0 2
1 3
  • 输出样例
3

3、样例说明

  • 时间 T=0 时,位于坐标方格的位置为 (1,1)。此时不能游向任意方向,因为相邻方向平台的高度都大于当前时间为 0 时的水位。
  • 时间 T=1 时,可以游到 (2,1);
  • 时间 T=2 时,可以游到 (2,1)和(1,2);
  • 时间 T=3 时,才可以游到 (2,2) 。 因为此时的水位是 3,坐标方格中的平台没有比水位 3 更高的,所以可以游向坐标方格中的任意位置。

4、数据范围

   n ≤ 1000 , 0 ≤ h ( i , j ) ≤ 1 0 6 n≤1000,0≤h(i,j)≤10^6 n1000,0h(i,j)106

二、思路

  谨以本实验证明AI的能力不够

PS:GPT4/Claude3均无法解决该问题,下附生成结果,具体内容不做解释。。。详细请咨询GPT(假如成功驯化,欢迎评论)

1、GPT4 - fail

  这个问题可以使用广度优先搜索(BFS)算法来解决。下面是对算法的详细解释以及使用C++实现的示例:

算法解释

  1. 首先定义四个方向:上、下、左、右。
  2. 创建一个队列来存储待探索的位置信息,队列中的每个元素包括位置 (x, y) 和到达该位置所需的时间 t
  3. 使用一个集合来记录已经访问过的位置,以避免重复访问。
  4. 从起始位置 (0, 0) 开始,将其加入队列和已访问集合中。
  5. 从队列中取出位置信息,检查其四个方向的相邻位置:
    • 如果相邻位置未被访问过且满足游动条件,则将其加入队列和已访问集合,并更新到达该位置所需的时间。
  6. 重复以上步骤,直到队列为空或者到达终点 (n-1, n-1)

C++ 实现

#include <iostream>
#include <vector>
#include <queue>
#include <set>
using namespace std;int minTimeToEscape(int n, vector<vector<int>>& heights) {vector<pair<int, int>> directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; // right, left, down, upauto isValid = [&](int x, int y, int t) {return x >= 0 && x < n && y >= 0 && y < n && max(t, heights[x][y]) < t + 1;};queue<tuple<int, int, int>> q; // (x, y, time)set<pair<int, int>> visited;q.push({0, 0, 0});visited.insert({0, 0});while (!q.empty()) {auto [x, y, t] = q.front();q.pop();if (x == n - 1 && y == n - 1) {return t; // Reached the destination}for (auto& dir : directions) {int nx = x + dir.first, ny = y + dir.second;if (visited.count({nx, ny}) == 0 && isValid(nx, ny, t)) {visited.insert({nx, ny});q.push({nx, ny, t + 1});}}}return -1; // No path found
}int main() {int n;cin >> n;vector<vector<int>> heights(n, vector<int>(n));for (int i = 0; i < n; ++i) {for (int j = 0; j < n; ++j) {cin >> heights[i][j];}}int result = minTimeToEscape(n, heights);cout << result << endl;return 0;
}

  minTimeToEscape 函数接受地牢大小 n 和高度矩阵 heights 作为参数,并返回到达终点所需的最短时间。它使用了一个队列和一个集合来执行广度优先搜索,并检查是否满足游动条件。

2、Claude3 - fail

问题分析

  这个问题可以用图论的方法来解决。我们可以把每个坐标点看作图中的一个顶点,相邻的坐标点之间有可以通行的边,边权为 0。问题转化为从起点 (1,1) 到终点 (n,n) 的最短路径问题。

  由于每个位置的水位随时间增加而上涨,所以我们需要在图上添加时间维度,将每个顶点复制 t 个,表示在不同时间点可以到达该顶点。相邻顶点之间的边权为 1,表示耗时 1 单位时间。

  对于任意两个相邻的顶点 (x,y,t) 和 (x’,y’,t+1),如果 max(h(x,y), h(x',y')) <= t+1,那么它们之间可以存在一条边,表示可以在 t+1 时刻从 (x,y) 移动到 (x’,y’)。

算法实现

  我们可以使用广度优先搜索 (BFS) 算法来找到从起点到终点的最短路径。具体步骤如下:

  1. 创建一个三维数组 dist来记录从起点到达每个位置 (x,y,t) 的最短时间。初始化 dist[0][0][0] = 0,其他位置为正无穷大。
  2. 创建一个队列 q,将起点 (0,0,0) 加入队列。
  3. 每次从队列中取出一个位置 (x,y,t),检查它的上下左右四个相邻位置 (x’,y’,t+1)。如果 max(h[x][y], h[x'][y']) <= t+1dist[x'][y'][t+1] > dist[x][y][t] + 1,更新 dist[x'][y'][t+1] 并将 (x’,y’,t+1) 加入队列。
  4. 当 (n-1,n-1) 出现在队列中时,返回对应的最短时间 dist[n-1][n-1][t]。如果队列为空仍未找到目标位置,返回 -1。

  下面是 C++ 代码实现:

#include <bits/stdc++.h>
using namespace std;const int dx[] = {-1, 1, 0, 0};
const int dy[] = {0, 0, -1, 1};int shortest_time(int n, vector<vector<int>>& h) {vector<vector<vector<int>>> dist(n, vector<vector<int>>(n, vector<int>(n+1, INT_MAX)));dist[0][0][0] = 0;queue<tuple<int, int, int>> q;q.push({0, 0, 0});while (!q.empty()) {int x, y, t;tie(x, y, t) = q.front();q.pop();if (x == n-1 && y == n-1) {return t;}for (int i = 0; i < 4; i++) {int nx = x + dx[i];int ny = y + dy[i];if (0 <= nx && nx < n && 0 <= ny && ny < n && max(h[x][y], h[nx][ny]) <= t+1) {if (dist[nx][ny][t+1] > dist[x][y][t] + 1) {dist[nx][ny][t+1] = dist[x][y][t] + 1;q.push({nx, ny, t+1});}}}}return -1;
}int main() {int n;cin >> n;vector<vector<int>> h(n, vector<int>(n));for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {cin >> h[i][j];}}cout << shortest_time(n, h) << endl;return 0;
}

  这个算法的时间复杂度是 O ( n 3 ) O(n^3) O(n3),空间复杂度是 O ( n 3 ) O(n^3) O(n3),其中 n n n 是地牢的大小。

3、个人拙见 - succeed

  本题目仅需获得最短耗时,不需要考虑动态规划回溯路径;本方法中每个A[i][j]是相对于已经走过的行、列的最短耗时,与未来没走过的路没有任何瓜葛~,亦不需要考虑未来的路 【贪心方法】???
PS:最终除了A[0][0]A[n-1][n-1]外,每个A[i][j]都可能是假的时间~

在这里插入图片描述

  • 初始化 A[0][0] = h[0][0]

    • 起点 (0,0) 到达自身的最短时间就是该位置的地势高度。
  • 初始化第一行和第一列的值

    • 起点 (0,0) 到达 (i,0) 或 (0,j) 的最短时间,等于当前位置的地势高度和上(左)一个位置的最短时间的最大值。
      • A[i][0] = max(h[i][0], A[i-1][0])
      • A[0][j] = max(h[0][j], A[0][j-1])
  • 递推其他位置的值

    • A[i][j] = max(h[i][j], min(A[i-1][j], A[i][j-1]))
    • 从起点 (0,0) 到达 (i,j) 的最短时间,等于当前位置的地势高度和上一个位置的最短时间的最大值,这里只需要考虑从上一个位置和左一个位置到达当前位置的最短时间。(瞬移是无敌的好嘛~)
  • 最终答案就是 A[n-1][n-1]

三、代码实现

//
// Created by Lenovo on 24-4-17.
//
#include <iostream>
using namespace std;
const int MAX = 1001;
int h[MAX][MAX];    // 地牢高度
int A[MAX][MAX];    // 动态规划int time(int n) {int i, j;A[0][0] = h[0][0];  // 起始点=地牢高度// 初始化for (i = 1; i < n; i++) {A[i][0] = max(h[i][0], A[i-1][0]);A[0][i] = max(h[0][i], A[0][i-1]);}for (i = 1; i < n; i++) {for (j = 1; j < n; j++) {
//            假定在方格内部游动不耗时// 耗时最短(0,0)——(n-1,n-1)~方向已确定,不必考虑往回游~int minlocal = min(A[i][j-1],  A[i-1][j]);A[i][j] = max(h[i][j], minlocal);}}return A[n-1][n-1];
}int main() {int n, i, j;cin>>n;for (i = 0; i < n; i++) {for (j = 0; j < n; j++) {cin>>h[i][j];}}cout<<time(n);return 0;
}
/*
2
0 2
1 3
*/
/*
3
3 9 7
4 5 4
8 3 5
*/

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

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

相关文章

力扣每日一题106:从中序与后序遍历序列构造二叉树

题目 中等 相关标签 相关企业 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,7], postorder …

OpenCV(五) —— 人脸识别模型训练与 Windows 下的人脸识别

本文主要内容&#xff1a; 如何训练 OpenCV 的人脸识别模型如何在 Windows 下利用 OpenCV 进行人脸识别 1、概述 人脸识别需要人脸模型&#xff08;特征集合&#xff09;的支持&#xff0c;人脸定位的速度与准确度取决于模型。 OpenCV 提供了已经训练好的模型&#xff0c;无…

KAN网络认识

首先&#xff0c;这是一个基于柯尔莫哥洛夫-阿诺德表示定理的网络。这个定理指出如果函数f是定义在有界域上的多变量连续函数&#xff08;即最终要拟合的非线性函数是连续的&#xff09;&#xff0c;那么该函数就可以表示为多个单变量、加法连续函数的有线组合。 对于机器学习…

大数据BI可视化(Echarts组件)项目开发-熟悉交互API5.0

全局echarts对象 init初始化 registerTheme注册主题 var mCharts echarts.init(document.querySelector("div"), itcast)registerMap地图图表 connect 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8&qu…

OpenCV(六) —— Android 下的人脸识别

本篇我们来介绍在 Android 下如何实现人脸识别。 上一篇我们介绍了如何在 Windows 下通过 OpenCV 实现人脸识别&#xff0c;实际上&#xff0c;在 Android 下的实现的核心原理是非常相似的&#xff0c;因为 OpenCV 部分的代码改动不大&#xff0c;绝大部分代码可以直接移植到 …

ubuntu安装LVGL/lv_img_conv并在thinkphp中进行调用生成bin文件

项目需求&#xff1a;需要处理图片成为bin文件&#xff0c;并以二进制的方式传给蓝牙设备&#xff0c;当前仅介绍如何安装&#xff0c;对lvgl功能和简介不做过多描述 项目库地址&#xff1a;https://github.com/lvgl/lv_img_conv 安装过程比较简单 一&#xff0c;确保node.j…

mall-cook本地部署运行

下载源代码 https://github.com/wangyuan389/mall-cook 下载好之后解压&#xff0c;删除.github和yarn.lock&#xff0c;因为使用pnpm 启动文档部署 切换到packages\mall-cook-document&#xff0c;删除yarn.lock&#xff0c;安装依赖包pnpm install 执行pnpm dev启动文档…

C语言/数据结构——(用双链表实现数据的增删查改)

一.前言 嗨嗨嗨&#xff0c;大家好久不见&#xff01;前面我们已经通过数组实现数据的增删查改、单链表实现数据的增删查改&#xff0c;现在让我们尝试一下使用双链表实现数据的增删查改吧&#xff01; 二.正文 如同往常一样&#xff0c;对于稍微大点的项目来说&#xff0c;…

推荐网站(2)今日热榜合集,看不同软件的热点事件

当我们想要看微博&#xff0c;今日头条&#xff0c;bilibili等等今日热点时&#xff0c;需要打开对应的app查看&#xff0c;但是有了这个网站我们可以看不同平台的热点消息&#xff0c;甚至京东&#xff0c;淘宝等购物软件&#xff0c;也能看到热销总榜。 链接直达&#xff1a;…

day-28 除自身以外数组的乘积

思路 利用两个空数组left&#xff08;left[i]表示nums下标从0到i的乘积&#xff09;和right&#xff08;right[i]表示nums下标从n-1到i的乘积&#xff09; 解题方法 返回数组nums[i]right[i1]*left[i-1],第一个元素和最后一个元素单独考虑 Code class Solution {public int[…

【计算机网络】计算机网络的定义和分类

一.定义 计算机网络并没有一个精确和统一的定义&#xff0c;在计算机网络发展的不同阶段&#xff0c;人们对计算机网络给出了不同的定义&#xff0c;这些定义反映了当时计算机网络技术的发展水平。 例如计算机网络早期的一个最简单定义&#xff1a;计算机网络是一些互连的、自…

c#Excel:2.写入Excel表 3.读取Excel表

--写入Excel表-- 该例首先从数据库aq中读取学生信息表staq(参考数据库章节)&#xff0c;然后将学生信息表中的数据写入Excel表格中 &#xff08;1&#xff09;在OfficeOperator类库项目的ExcelOperator类中定义索引器&#xff0c;用于获取Excel表格中的单元格&#xff0c;代码…

队列集使用

文章目录 前言一、功能描述二、功能实现 前言 在实际使用中我们可能要从多个队列中得到数据&#xff0c;就需要队列集。 一、功能描述 创建两个队列Queue1、Queue2。Task1往Queue1写数据、Task2往Queue2写数据。Task3使用QueueSet监测这两个队列。 二、功能实现 创建两个队列…

ArcGIS软件:地图投影的认识、投影定制

这一篇博客介绍的主要是如何在ArcGIS软件中查看投影数据&#xff0c;如何定制投影。 1.查看地图坐标系、投影数据 首先我们打开COUNTIES.shp数据&#xff08;美国行政区划图&#xff09;&#xff0c;并点击鼠标右键&#xff0c;再点击数据框属性就可以得到以下的界面。 我们从…

活动图与状态图:UML中流程图的精细化表达——专业解析系统动态性与状态变迁

流程图是一种通用的图形表示法&#xff0c;用以展示步骤、决策和循环等流程控制结构。它通常用于描述算法、程序执行流程或业务过程&#xff0c;关注于任务的顺序执行。流程图强调顺序、分支和循环&#xff0c;适用于详细说明具体的处理步骤&#xff0c;图形符号相对基础和通用…

Android NDK开发——Android Studio 3.5.2安装与配置踩坑

Android NDK开发——Android Studio 3.5.2安装与配置踩坑 一、Android Studio下载二、配置踩坑报错1&#xff1a;Failed to install the following Android SDK packages as some licences have not been accepted报错2&#xff1a;No toolchains found in the NDK toolchains …

C语言实战项目--贪吃蛇

贪吃蛇是久负盛名的游戏之一&#xff0c;它也和俄罗斯⽅块&#xff0c;扫雷等游戏位列经典游戏的行列。在编程语言的教学中&#xff0c;我们以贪吃蛇为例&#xff0c;从设计到代码实现来提升大家的编程能⼒和逻辑能⼒。 在本篇讲解中&#xff0c;我们会看到很多陌生的知识&…

Unity 性能优化之数据面板(Statistics)(一)

提示&#xff1a;仅供参考&#xff0c;有误之处&#xff0c;麻烦大佬指出&#xff0c;不胜感激&#xff01; 文章目录 前言一、unity 统计数据面板&#xff08;Statistics&#xff09;1.Audio属性2.Graphics属性 二、什么是Draw Call&#xff1f;三、Unity3D stats也可以通过代…

OpenCV的周期性噪声去除滤波器(70)

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇:OpenCV如何通过梯度结构张量进行各向异性图像分割(69) 下一篇 :OpenCV如何为我们的应用程序添加跟踪栏(71) 目录 目标 理论 如何消除傅里叶域中的周期性噪声&#xff1f; 源代码 解释 结果 目…

设计模式之数据访问对象模式

在Java编程的浩瀚星海中&#xff0c;有一个模式低调却强大&#xff0c;它像是一位默默无闻的超级英雄&#xff0c;支撑起无数应用的数据脊梁——那就是数据访问对象&#xff08;DAO, Data Access Object&#xff09;模式&#xff01;想象一下&#xff0c;如果你能像操纵魔法一样…