首页 > 其他分享 >数字三角形模型

数字三角形模型

时间:2023-05-02 16:25:05浏览次数:48  
标签:数字 右下角 int 模型 路径 矩阵 方格 左上角 三角形

数字三角形模型

给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。

image-20230417190129709

状态表示:\(f[i][j]\)代表从\((1,1)\)到\((i,j)\)的路径和最大值

状态属性:\(MAX\)

状态计算:\((i,j)\)可以由\((i-1,j-1)和(i-1,j)\)转移

\[f[i][j]=max(f[i-1][j],f[i-1][j-1])+a[i][j] \]

状态初始:初始化为\(-INF\), \(f[1][1] = a[1][1]\)

答案呈现:\(\sum max(f[n][i])\)

const int N = 5e2 + 10;

int dp[N][N];
int a[N][N];

void slove()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= i; ++j)
            cin >> a[i][j];	
    for (int i = 0; i <= n; ++i)
        for (int j = 0; j <= i + 1; ++j)
            dp[i][j] = -INF;
    dp[1][1] = a[1][1];
    for (int i = 2; i <= n; ++i)
        for (int j = 1; j <= i; ++j)
            dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1]) + a[i][j];
    int ans = -INF;
    for (int i = 1; i <= n; ++i)
        ans = max(ans, dp[n][i]);
    cout << ans << endl;
}

摘花生

给定一个 \(n \times m\) 的矩阵,矩阵中每个元素的值非负,现在你需要从矩阵的左上角\((1,1)\)到右下角\((n,m)\),每一步只能向右或向下走,请你找到一条路径使得该路径上经过的元素的和最大,请你求出最大的和

image-20230502150842785

\(1 \le n,m \le 100\)

题解:线性DP \(O(n^2)\)

  • 状态表示:

\(f[i][j]\)代表从起点\((1,1)\)到\((i,j)\)的所有路径中的元素之和最大值

  • 状态属性:\(MAX\)

  • 状态计算:按照最后一步从上面或者左边过来进行划分

  1. 最后一步从上面过来:\(f[i-1][j]\)
  2. 最后一步从左边过来:\(f[i][j-1]\)

\[f[i][j] = max(f[i-1][j],f[i][j-1])+a[i][j] \]

  • 状态初始:\(f[1][1] = a[1][1],f[i][j] = 0\)

  • 答案呈现:\(f[n][m]\)

const int N = 1e2 + 10;

int n, m;
int a[N][N];
int f[N][N];

void solve()
{
    cin >> n >> m;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
        {
            cin >> a[i][j];
            f[i][j] = 0;
        }
    f[1][1] = a[1][1];
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            f[i][j] = max(f[i - 1][j] + a[i][j], f[i][j - 1] + a[i][j]);
    cout << f[n][m] << endl;
}

最低通行费

一个商人穿过一个 \(N×N\) 的正方形的网格,去参加一个非常重要的商务活动。

他要从网格的左上角进,右下角出。

每穿越中间 \(1\) 个小方格,都要花费 \(1\) 个单位时间。

商人必须在 \((2N−1)\) 个单位时间穿越出去。

而在经过中间的每个小方格时,都需要缴纳一定的费用。

这个商人期望在规定时间内用最少费用穿越出去

\(1 \le n \le 100\)

题解:线性DP \(O(n^2)\)

我们发现这名商人最少从这个正方形网格中穿出去的时间都需要\(2N-1\)个单位,说明他不能走回头路,只能往下或者往右走,那么这道题又等价于上面那题摘花生了,\(dp\)过程不再赘述

const int N = 1e2 + 10;

int n;
int a[N][N];
int f[N][N];

void solve()
{
    cin >> n;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j)
            cin >> a[i][j];
    for (int i = 0; i <= n; ++i)
        for (int j = 0; j <= n; ++j)
            f[i][j] = INF;
    f[1][1] = a[1][1];
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j)
            f[i][j] = min({f[i][j], f[i - 1][j] + a[i][j], f[i][j - 1] + a[i][j]});
    cout << f[n][n] << endl;
}

方格取数

设有 \(n×n\) 的方格图,我们在其中的某些方格中填入正整数,而其它的方格中则放入数字\(0\)。如下图所示:

2.gif

某人从图中的左上角 \(A\) 出发,可以向下行走,也可以向右行走,直到到达右下角的 \(B\) 点

在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字\(0\))

此人从 \(A\) 点到 \(B\) 点共走了两次,试找出两条这样的路径,两条路径上的点可以重复,使得取得的数字和为最大

\(1 \le n \le 10\)

题解:线性DP \(O(n^3)\)

  • 状态表示:\(O(n^4)\)

\(f[i_1][j_1][i_2][j_2]\)代表所有从\((1,1)\)到\((i_1,j_1)\)和从\((1,1)\)到\((i_2,j_2)\)的两条路线中数字之和的最大值

  • 状态属性:\(MAX\)

  • 状态计算:可以从上或者从左到\((i_1,j_1)\),可以从上或者从左到\((i_2,j_2)\),那么一共有\(2 \times 2 = 4\)种选择 \(O(1)\)

  1. 从左边到\((i_1,j_1)\),从左边到\((i_2,j_2)\):\(f[i_1][j_1-1][i_2][j_2-1]\)
  2. 从左边到\((i_1,j_1)\),从上边到\((i_2,j_2)\):\(f[i_1][j_1-1][i_2-1][j_2]\)
  3. 从上边到\((i_1,j_1)\),从左边到\((i_2,j_2)\):\(f[i_1-1][j_1][i_2][j_2-1]\)
  4. 从上边到\((i_1,j_1)\),从上边到\((i_2,j_2)\):\(f[i_1-1][j_1][i_2-1][j_2]\)

注意:如果\((i_1,j_1)\) = \((i_2,j_2)\),那么我们只能取一次该位置上的数字

\[f[i_1][j_1][i_2][j_2] = max({f[i_1 - 1][j_1][i_2 - 1][j_], f[i_1 - 1][j_1][i_2][j_2 - 1], f[i_1][j_1 - 1][i_2 - 1][j_2], f[i_1][j_1 - 1][i_2][j_2 - 1]}) + g[i_1][j_1] \\ (i_1,j_1) ==(i_2,j_2) \]

\[f[i_1][j_1][i_2][j_2] = max({f[i_1 - 1][j_1][i_2 - 1][j_], f[i_1 - 1][j_1][i_2][j_2 - 1], f[i_1][j_1 - 1][i_2 - 1][j_2], f[i_1][j_1 - 1][i_2][j_2 - 1]}) + g[i_1][j_1]+g[i_2][j_2] \\ (i_1,j_1)\neq(i_2,j_2) \]

  • 状态优化:\(O(n^3)\)

我们发现只有步数一样的时候两条路线才有可能重合,设走过的步数为\(k\),那么如果\(i_1=i_2\),就说明两条路线在这个点重合了,该点坐标为\((i_1,k-i_1)\),所以我们可以将状态合并为:

\(f[k][i_1][i_2]\)代表经过\(k\)步后,一条路线现在经过的点的横坐标为 \(i_1\),另一条路线现在经过的点的横坐标为\(i_2\),两条路线中数字之和的最大值

状态计算和上面一样,不再赘述

状态初始:\(f[2][1][1] = g[1][1]\)

答案呈现:\(f[2 * n][n][n]\)

const int N = 12, M = 4e5 + 10;

int n;
int g[N][N];
int f[N << 1][N][N];

void solve()
{
    cin >> n;
    int a, b, c;
    while (cin >> a >> b >> c, a || b || c)
    {
        g[a][b] = c;
    }
    f[2][1][1] = g[1][1];
    for (int k = 3; k <= 2 * n; ++k)
        for (int i1 = 1; i1 <= n; ++i1)
            for (int i2 = 1; i2 <= n; ++i2)
            {
                int j1 = k - i1, j2 = k - i2;
                if (j1 >= 1 && j1 <= n && j2 >= 1 && j2 <= n)
                {
                    if (i1 == i2)
                        f[k][i1][i2] = max({f[k - 1][i1 - 1][i2 - 1], f[k - 1][i1][i2 - 1], f[k - 1][i1 - 1][i2], f[k - 1][i1][i2]}) + g[i1][j1];
                    else
                        f[k][i1][i2] = max({f[k - 1][i1 - 1][i2 - 1], f[k - 1][i1][i2 - 1], f[k - 1][i1 - 1][i2], f[k - 1][i1][i2]}) + g[i1][j1] + g[i2][j2];
                }
            }
    cout << f[2 * n][n][n] << endl;
}

传纸条

给定一个 \(n \times m\) 的矩阵,矩阵中每个元素的值非负,现在你需要从矩阵的左上角\((1,1)\)到右下角\((n,m)\),每一步只能向右或向下走,然后再从矩阵的右下角\((n,m)\)到左上角\((1,1)\),每一步只能向左或向上走,且之前经过的点不能再经过,请你找到一条路径使得该路径上经过的元素的和最大,请你求出最大的和

题解:线性DP

不难发现任意一条从矩阵的右下角\((n,m)\)到左上角\((1,1)\)的路线都能将其方向反转后变成从矩阵的左上角\((1,1)\)到右下角\((n,m)\)的一条路线,且经过的点不变

所以我们可以将题目转化为从矩阵的左上角\((1,1)\)到右下角\((n,m)\)走两次,每一步只能向右或向下走,且第二次走的路线中的点不能和第一次经过的点有交集

那么实际上已经和方格取数的\(dp\)模型非常接近了,我们只要解决两次经过的点不存在交集的问题即可,那么实际上我们可以证明方格取数的\(dp\)模型在这道题同样适用于解决两次经过的点不存在交集的问题,下面请看证明:

如果两条最优线路是交叉的

image-20230502155849518

我们可以将其交叉的部分进行交换变成:

image-20230502155955590

所以所有存在交叉的最优线路都能转化为存在交点的两条路线,我们只需要考虑如何解决两条路线不交叉,但是存在交点的情况

image-20230502160213954

根据最优路线我们知道\(w_A=w_B=0\),所以我们可以微调其中一条路线,使得两条路径不经过重合点,且不影响路线的最优性

const int N = 55, M = 4e5 + 10;

int n, m;
int g[N][N];
int f[N << 1][N][N];

void solve()
{
    cin >> n >> m;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            cin >> g[i][j];
    f[2][1][1] = g[1][1];
    for (int k = 3; k <= n + m; ++k)
        for (int i1 = 1; i1 <= n; ++i1)
            for (int i2 = 1; i2 <= n; ++i2)
            {
                int j1 = k - i1, j2 = k - i2;
                if (j1 >= 1 && j1 <= m && j2 >= 1 && j2 <= m)
                {
                    if (i1 == i2)
                        f[k][i1][i2] = max({f[k - 1][i1 - 1][i2 - 1], f[k - 1][i1][i2 - 1], f[k - 1][i1 - 1][i2], f[k - 1][i1][i2]}) + g[i1][j1];
                    else
                        f[k][i1][i2] = max({f[k - 1][i1 - 1][i2 - 1], f[k - 1][i1][i2 - 1], f[k - 1][i1 - 1][i2], f[k - 1][i1][i2]}) + g[i1][j1] + g[i2][j2];
                }
            }
    cout << f[n + m][n][n] << endl;
}

标签:数字,右下角,int,模型,路径,矩阵,方格,左上角,三角形
From: https://www.cnblogs.com/Zeoy-kkk/p/17367819.html

相关文章

  • Linux的IO模型
    一、基本概念五种IO模型包括:阻塞IO、非阻塞IO、IO多路复用、信号驱动IO、异步IO。首先需要了解下系统调用的几个函数和基本概念。1.1简单介绍几个系统调用函数由于我对于C语言不熟悉,几个系统函数参考了一些文章,如果错误欢迎指出!recvfromLinux系统提供给用户用于接收网络IO的系统接......
  • 中台设计- 业务中台设计模型(5/5)
    中心三层模型0级功能架构图0级技术架构图0级业务数据流图1级功能架构图业务建模功能需求汇总功能抽象汇总系统应用一级功能二级功能功能说明业务领域业务实体领域能力订单管理订单列表订单列表交易域订单生成订单订单发货库存域面单查询面单......
  • 《花雕学AI》27:如何在ChatGPT时代提高数字媒体艺术的原创性和价值?
    引言数字媒体艺术是指使用各种数字、信息技术制作的各种形式的有独立审美价值的艺术作品,具有模拟现实的虚拟性、艺术创造的想象性、交互性和使用网络媒体的基本特征。数字媒体艺术是一个跨自然科学、社会科学和人文科学的综合性学科,集中体现了“科学、艺术和人文”的理念。数字媒......
  • 软件工程师能力模型探讨
    软件工程师能力模型探讨高级JAVA工程师通用技能ExpertJavaknowledge  JAVA知识专家级Object-OrientedDesignPatterns  面向对象与设计模式High-leveldesignskills  高层模块设计Designingforspecificrequirements(e.g.security,scalability,optimization) ......
  • 2023-05-01:给你一个整数 n , 请你在无限的整数序列 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1
    2023-05-01:给你一个整数n,请你在无限的整数序列[1,2,3,4,5,6,7,8,9,10,11,...]中找出并返回第n位上的数字。1<=n<=2^31-1。输入:n=11输出:0解释:第11位数字在序列1,2,3,4,5,6,7,8,9,10,11,...里是0,它是10的一部分。答案2023-05-01:该......
  • 2023-05-01:给你一个整数 n , 请你在无限的整数序列 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1
    2023-05-01:给你一个整数n,请你在无限的整数序列[1,2,3,4,5,6,7,8,9,10,11,...]中找出并返回第n位上的数字。1<=n<=2^31-1。输入:n=11输出:0解释:第11位数字在序列1,2,3,4,5,6,7,8,9,10,11,...里是0,它是10的一部分。答案2023-05-01:......
  • 什么是Auto GPT-4? OpenAI 最新语言模型概览
    动动发财的小手,点个赞吧!人工智能正在快速发展,近年来最令人兴奋的发展之一是创建可以生成类似人类文本的语言模型。领先的人工智能研究机构OpenAI最近发布了其最新的语言模型AutoGPT-4。在什么是AutoGPT-4?OpenAI最新语言模型概述一文,我们将概述什么是AutoGPT-4、Auto......
  • 第五节 盒子模型
    day05-盒子模型目标:掌握盒子模型组成部分,使用盒子模型布局网页区域01-选择器结构伪类选择器基本使用作用:根据元素的结构关系查找元素。li:first-child{ background-color:green;}:nth-child(公式)提示:公式中的n取值从0开始。伪元素选择器作用:创建虚拟元......
  • Facebook刷新开放域问答SOTA:模型训模型!Reader当Teacher!
    文|Sherry不是小哀编|小轶一部问答系统发展史就是一部人工智能发展史。早在1950年的图灵测试就提出:如果人类无法通过问答将机器和人区分开,那么这个机器就可以被认为具有智能。问答系统和人工智能有着密不可分的关系。从基于规则和结构化数据的自动问答,到基于精细设计神经网......
  • 无线键盘无法打开数字键盘numlock的解决方法
    1、把以下文本另存为后缀为vbs的脚本,运行即可打开数字小键盘。2、按Win+R,运行shell:startup3、把脚本拖入打开的窗口。以后每次开机都会运行此脚本,打开NUMLOCK数字键盘。'按Win+R,运行:shell:startup把脚本拖入其中SetKeyToPress=WScript.CreateObject("WScript.Shell")KeyToPr......