算法竞赛备赛进阶之数字三角形模型训练

news2024/11/23 17:21:46

目录

1.数字三角形

2.摘花生.1015

3.最低通行费

4.方格取数


在算法竞赛中,有时候会遇到一些图形相关的题目,需要运用图论相关的知识进行求解。今天我们将一起探讨一个比较常见的模型——数字三角形模型。

在数字三角形模型中,每个位置的值是唯一的,而且从前一个位置到当前位置只能沿着三角形的一条边走。以一个数字三角形的顶端开始,可以通过向下或向右移动一步来达到下一个位置,依此类推。

以下是一个数字三角形模型的例子:

1  
23  
345  
4567  
56789

在这个例子中,从顶端开始,分别可以到达以下位置:

  • 第一行:1
  • 第二行:2, 3
  • 第三行:3, 4, 5
  • 第四行:4, 5, 6, 7
  • 第五行:5, 6, 7, 8, 9

现在,假设有一个数字三角形,每个位置的值都是非负整数,并且每个位置的值不能超过该位置的行数。我们需要找出从顶端到最后一行的一个路径,使得路径上所有位置的总和最大。这个问题可以通过动态规划(DP)的方法来解决。

以下是一个使用动态规划解决该问题的C++代码示例:

#include <bits/stdc++.h>  
using namespace std;  
const int MAXN = 100005;  
int dp[MAXN], pre[MAXN];  
int main() {  
    int n;  
    scanf("%d", &n);  
    for (int i = 1; i <= n; i++) {  
        for (int j = i; j >= 1; j--) {  
            scanf("%d", &dp[j]);  
            pre[j] = j - 1;  
        }  
    }  
    int ans = dp[1];  
    for (int i = 2; i <= n; i++) {  
        int mn = INT_MAX;  
        for (int j = i; j >= 1; j--) {  
            mn = min(mn, dp[j]);  
            dp[j] += mn * (i - pre[j] - 1);  
        }  
        pre[i] = i - 1;  
        ans = max(ans, dp[i]);  
    }  
    printf("%d\n", ans);  
    return 0;  
}

在这个代码中,我们首先读入数字三角形的每一行的整数,并将它们存储在数组dp中,同时建立一个pre数组来存储每个位置的最前面一个位置。然后,我们通过两次循环遍历整个数字三角形:第一次循环中,我们通过遍历每个位置的最前面一个位置,找到从该位置开始的最大和路径;第二次循环中,我们通过遍历每个位置的最前面一个位置,计算从该位置开始的最大和路径,并更新答案。最后,我们输出答案。

需要注意的是,以上代码仅适用于非负整数的情况。如果数字三角形中的值可能为负数,那么需要做一些修改。例如,可以在dp数组中存储每个位置的值和该位置的最前面一个位置的差的绝对值,然后在第二次循环中计算最大和路径时加上这个值。

1.数字三角形

给出了一个数字三角形,从三角形的顶部到底部有多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,累加和最大的路径称为“最佳路径”。题目的任务就是求出最佳路径上的数字之和。

注意:路径上的每一步只能从一个数走到下一层和它最近的左边的数或者右边的数。

#include<iostream>
#include<cstdio>
using namespace std;
 
#define MAX_NUM 100
int d[MAX_NUM+10][MAX_NUM+10];
int N;
 
int MaxSum(int r,int j)  //递归求解最大路径和 
{
    if(r == N)
        return d[r][j];
    int sum1 = MaxSum(r+1,j);
    int sum2 = MaxSum(r+1,j+1);
    if(sum1 > sum2)
        return sum1 + d[r][j];
    return sum2 + d[r][j];
}
 
int main()
{
    int m;
    cin>>N;
    for(int i = 1;i <= N; i++)
        for(int j = 1;j <= i; j++)
            cin >> d[i][j];
    cout << MaxSum(1,1);
    return 0;
}

5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5

2.摘花生.1015

Hello Kitty想摘点花生送给她喜欢的米老鼠。

她来到一片有网格状道路的矩形花生地(如下图),从西北角进去,东南角出来。

地里每个道路的交叉点上都有种着一株花生苗,上面有若干颗花生,经过一株花生苗就能摘走该它上面所有的花生。

Hello Kitty只能向东或向南走,不能向西或向北走。

问Hello Kitty最多能够摘到多少颗花生。

传统的思考方式:阶段、决策、最优子结构、无后效性。

从集合角度来思考DP问题——闫氏思考法

动态规划

  1. 状态表示f[i, j]:

    a) 集合 所有从(1,1)走到(i,j)的路线的最大值

    b) 属性:Max/Min/数值

  2. 状态计算 - 对应的是集合的划分

重要集合划分依据:“最后”,最后一步很关键,像本题目中的从上面下来,还是从左边过来。它的划分原则有不重复和不漏,当然在求Max和Min的时候不一定满足不重复原则。

#include<iostream>
#include<algorithm>
​
using namespace std;
​
const int N = 110;
​
int n, m;
int w[N][N];
int f[N][N];
​
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d",&n, &m);
        for(int i = 1;i <= n; i++)
        {
            for(int j = 1;j <= m; j++)
            {
                scanf("%d", &w[i][j]);
            }
        }
        
        for(int i = 1;i <= n; i++)
        {
            for(int j = 1;j <= m; j++)
            {
                f[i][j] = max(f[i-1][j], f[i][j-1]) + w[i][j];
            }
        }
        printf("%d\n", f[n][m]);
    }
    return 0;
}

3.最低通行费

一个商人穿过一个N×N的正方形的网格,去参加一个非常重要的商务活动。他要从网格的左上角进,右下角出。每穿越中间1个小方格,都要花费1个单位时间。商人必须在(2N-1)个单位时间穿越出去。而在经过中间的每个小方格时,都需要缴纳一定的费用。这个商人期望在规定时间内用最少费用穿越出去。请问至少需要多少费用?

注意:不能对角穿越各个小方格(即,只能向上下左右四个方向移动且不能离开网格)。

【输入样例] 5 1 4 6 8 10 2 5 7 15 17 6 8 9 18 20 10 11 12 19 21 20 23 25 29 33 【输出样例】 109

#include<iostream>
#include<algorithm>
​
using namespace std;
​
const int N = 110, INF = 1e9;
​
int m;
int w[N][N];
int f[N][N];
​
int main()
{
    scanf("%d", &m);
    for(int i = 1;i <= m; i++)
    {
        for(int j = 1;j <= m; j++)
        {
            scanf("%d", &w[i][j]);
        }
    }
    
    for(int i = 1;i <= m; i++)
    {
        for(int j = 1;j <= m; j++)
        {
            if(i == 1 && j == 1) f[i][j] = w[i][j];
            else
            {
                f[i][j] = INF;
                if(i > 1) f[i][j] = min(f[i][j], f[i-1][j]) + w[i][j];
                if(j > 1) f[i][j] = min(f[i][j], f[i][j-1]) + w[i][j];
            }
        }
    }
    printf("%d\n",f[m][m]);
    return 0;
}

4.方格取数

题目描述 设有N×N的方格图,我们在其中的某些方格中填入正整数,而其它的方格中则放入数字0。如下图所示:

某人从图中的左上角A出发,可以向下行走,也可以向右行走,直到到达右下角的B点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。

此人从A点到B点共走了两次,试找出两条这样的路径,使得取得的数字和为最大。

f[i] [j]表示所有从[1] [1]走到[i] [j]的路径最大值

f[i] [j] = max(f[i-1] [j], f[i] [j-1]) + w[i] [j];

走两次:

f[i1] [j1]和f[i2] [j2]表示所有从[1] [1],[1] [1]走到[i1] [j1],[i2] [j2]的路径最大值

f[i] [j] = max(f[i-1] [j], f[i] [j-1]) + w[i] [j];

处理“同一个格子不能被重复选择”

只有在i1+j1 == i2+j2,那么两条路径的格子才可能会重合

f[k, i1, i2]表示从所有[1] [1],[1] [1]分别走到(i1, k-i1)和(i2, k-i2)的路径的最大值

k表示两条路线当前走到的格子的横纵坐标之和。

#include<iostream>
#include<algorithm>
​
using namespace std;
​
const int N = 15;
​
int n;
int w[N][N];
int f[N-2][N][N];
​
int w[N][N];
int f[N*2][N][N];
​
int main()
{
    scanf("%d", &n);
    
    int a, b, c;
    while(cin >> a >> b >> c, a || b || c)
        w[a][b] = c;
    
    for(int k = 2;k <= n+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)
                {
                    int t = w[i1][j1];
                    if(i1 != i2) t += w[i2][j2];
                    int &x = f[k][i1][j1];
                    x = max(x, f[k-1][i1-1][i2-1] + t);
                    x = max(x, f[k-1][i1-1][i2] + t);
                    x = max(x, f[k-1][i1][i2-1] + t);
                    x = max(x, f[k-1][i1][i2] + t);
                }
            }
        }
    }
    printf("%d\n",f[n+n][n][n]);
    return 0;
}

复写一遍:

#include<iostream>
#include<algorithm>
​
using namespace std;
​
const int N = 15;
int n;
int w[N][N];
int f[N*2][N][N];
​
int main()
{
    scanf("%d", &n);
    int a, b, c;
    while(cin >> a >> b >> c, a || b || c)
        w[a][b] = c;
    
    for(int k = 1;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)
                {
                    int t = w[i][j];
                    if(i1 != i2) t += w[i2][j2];
                    int &x = f[k][i1][i2];
                    x = max(x, f[k-1][i1-1][i2-1] + t);
                    x = max(x, f[k-1][i1-1][i2] + t);
                    x = max(x, f[k-1][i1][i2-1] + t);
                    x = max(x, f[k-1][i1][i2] + t);
                }
            }
        }
    }
    printf("%d", f[n+n][n][n]);
    return 0;
}

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

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

相关文章

Redis 群集模式

目录 1 Redis 群集模式 1.1 集群的作用&#xff0c;可以归纳为两点 1.2 Redis集群的数据分片 2 搭建Redis 群集模式 2.1 开启群集功能 2.2 启动redis节点 2.3 启动集群 2.4 测试群集 1 Redis 群集模式 集群&#xff0c;即Redis Cluster&#xff0c;是Redis 3.0开始引入…

Android攻城狮学鸿蒙 -- 点击事件

具体参考&#xff1a;华为官网学习地址 1、点击事件&#xff0c;界面跳转 对于一个按钮设置点击事件&#xff0c;跳转页面。但是onclick中&#xff0c;如果pages前边加上“/”&#xff0c;就没法跳转。但是开发工具加上“/”才会给出提示。不知道是不是开发工具的bug。&#…

用正则表达式验证用户名和跨域postmessage

正则验证用户名 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </hea…

redis命令学习

redis命令学习 redis的类型分为&#xff1a; string类型hash类型list类型set类型sortedset类型 string类型命令 set key value 设置值&#xff0c;key是键 value是值get key 根据键获取值setex key second value 设置值有效时间 second 是时间setnx key value 只有key不存在…

JSP旅游平台管理

本系统采用基于JAVA语言实现、架构模式选择B/S架构&#xff0c;Tomcat7.0及以上作为运行服务器支持&#xff0c;基于JAVA、JSP等主要技术和框架设计&#xff0c;idea作为开发环境&#xff0c;数据库采用MYSQL5.7以上。 开发环境&#xff1a; JDK版本&#xff1a;JDK1.8 服务器&…

【19】c++设计模式——>桥接模式

桥接模式的定义 C的桥接模式&#xff08;Bridge Pattern&#xff09;是一种结构型设计模式&#xff0c;它将抽象部分与实现部分分离&#xff0c;使得它们可以独立地变化。桥接模式的核心思想是利用组合关系代替继承关系&#xff0c;将系统划分成多个独立的、功能不同的类层次结…

Spring实例化源码解析之Custom Events下集(九)

上集从官网的角度讲解了基本的使用和源码的内容&#xff0c;没有深入的进行分析&#xff0c;本章将从源码的角度分析ApplicationEvent、ApplicationListener、ApplicationEventMulticaster这三者之间的关系。 initApplicationEventMulticaster 上一章后续部分给出了源码的含义…

数据驱动智能护理:看AI如何塑造医疗领域,为灰暗夕阳带来新的曙光

近年来&#xff0c;人工智能的应用正日益渗透到医疗领域&#xff0c;呈现出无限的潜力和前景。技术的不断进步和全球医疗挑战的不断涌现&#xff0c;使得AI成为改善医疗保健质量、提高患者生活水平的强大工具。从疾病的早期诊断到治疗计划的制定&#xff0c;再到医疗管理和患者…

IP 子网划分(VLSM)

目录 一、 为什么要划分子网 二、如何划分子网 1、划分两个子网 2、划分多个子网 一、 为什么要划分子网 假设有一个B类IP地址172.16.0.0&#xff0c;B类IP的默认子网掩码是 255.255.0.0&#xff0c;那么该网段内IP的变化范围为 172.16.0.0 ~ 172.16.255.255&#xff0c;即…

IDEA的database工具以及对比两个数据库之间的差异(比DBVisualizer和DBeaver方便)

背景 其实IDEA里有个非常好用的database工具&#xff0c;用来连数据库&#xff0c;能连的数据非常多&#xff0c;最重要的是还带有对比数据库差异的工具。 唯一有点不好就是这个是 intellij idea的ultimate edition版本才有&#xff0c;对于社区版本&#xff08;community ed…

Tomcat自启动另一种方法

Tomcat自启动另一种方法 问题&#xff1a; 不知道怎么回事&#xff0c;好几台电脑都可以开机自启动tomcat&#xff0c;正常运行项目。一样的配置一样的操作流程&#xff0c;偏偏要运行的机器开机自启动后&#xff0c;项目不能运行&#xff0c;手动重启tomcat又可以用了。网上…

【案例分享】企业常用IPSec VPN实现

【微|信|公|众|号&#xff1a;厦门微思网络】 【微思网络www.xmws.cn&#xff0c;成立于2002年&#xff0c;专业培训21年&#xff0c;思科、华为、红帽、ORACLE、VMware等厂商认证及考试&#xff0c;以及其他认证PMP、CISP、ITIL等】 组网需求 如图1所示&#xff0c;RouterA为…

图像处理与计算机视觉--第五章-图像分割-自适应阈值分割

文章目录 1.自适应阈值分割介绍2.自适应阈值函数参数解析3.高斯概率函数介绍4.自适应阈值分割核心代码5.自适应阈值分割效果展示6.参考文章及致谢 1.自适应阈值分割介绍 在图片处理过程中&#xff0c;针对铺前进行二值化等操作的时候&#xff0c;我们希望能够将图片相应区域内所…

数字IC前端学习笔记:数字乘法器的优化设计(Wallace Tree乘法器)

相关阅读 数字IC前端https://blog.csdn.net/weixin_45791458/category_12173698.html?spm1001.2014.3001.5482 进位保留乘法器依旧保留着阵列的排列规则&#xff0c;只是进位是沿斜下角&#xff0c;如果能使用树形结构来规划这些进位保留加法器&#xff0c;就能获得更短的关键…

ToBeWritten之让响应团队参与并做好沟通

也许每个人出生的时候都以为这世界都是为他一个人而存在的&#xff0c;当他发现自己错的时候&#xff0c;他便开始长大 少走了弯路&#xff0c;也就错过了风景&#xff0c;无论如何&#xff0c;感谢经历 转移发布平台通知&#xff1a;将不再在CSDN博客发布新文章&#xff0c;敬…

网页动画科普LLM原理;淘宝推出AI试衣间;爆火的AI极简人像;100天创业日程表;Llama 2详解 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f525; Meta Connect 2023&#xff0c;发布基于 LLama 2 的AI聊天助手和虚拟角色 9月27日-28日&#xff0c;Meta 举办了年度重要会议 Meta Co…

vue3 + vite项目使用SVG图标

我们在开发一个项目时常会用到一些图标&#xff0c;有些图标在有限的图标库中却是没有&#xff0c;因此少数的图标需要我们去网上查找&#xff0c;或是自定义一些专用的图标。一般很少有图标库满足现实的项目开发&#xff0c;这时将推荐使用 iconify 这个图标库&#xff0c;几乎…

Zabbix 监控系统安装和部署

Zabbix 监控系统安装和部署 一、zabbix 是什么&#xff1f;1.1、zabbix 监控原理&#xff08;重点&#xff09;1.2、Zabbix 6.0 新特性1.3、Zabbix 6.0 功能组件1.4、数据库1.5、Web 界面1.6、Zabbix Agent1.7、Zabbix Proxy1.8、Java Gateway 二、部署Zabbix 6.02.1、 解决 za…

通达信指标预警信号,自动发送给微信好友1.0

1.功能介绍&#xff1a;十一节假日期间写了一个&#xff0c;可将股票指标预警信号&#xff0c;自动发送给微信好友/微信群&#xff08;即电脑端的消息&#xff0c;通过模拟微信操作可在手机上显示&#xff09;。本工具按通达信写的&#xff0c;如果大智慧&#xff0c;同花顺也能…

Flutter环境搭建及新建项目

一、下载安装压缩包 https://storage.flutter-io.cn/flutter_infra_release/releases/stable/windows/flutter_windows_3.10.6-stable.zip 二、解压缩 解压之后&#xff0c;将里面的flutter整体拿出来 三、配置环境变量 将flutter/bin全路径配置到系统环境变量里面 四、运行…