AcWing算法提高课笔记——数字三角形

news2024/11/15 5:44:53

本文给出了几道数字三角形模型的题解。

数字三角形模型通常给定一个矩阵,从矩阵的左上角走到右下角,每次只能向右走或者向下走,求最大值或者最小值。

这种问题可以用f[i, j]来表示从[1, 1]走到[i, j]处的Max\Min,有状态转移方程:

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

如果是走两遍,就用f[k, i1, i2]表示从[1, 1]走到[i1, j1]和[i2, j2]处的Max\Min,其中i1 + j1 = k = i2 + j2。状态转移方程为:

f[k, i1, i2] = max(f[k - 1, i1 - 1, i2], f[k - 1, i1, i2 - 1], f[k - 1, i1, i2], f[k - 1, i1 - 1, i2 - 1]) + a[i, j]

本题所有题目都来自AcWing算法提高课。

文章目录

  • 摘花生
        • 输入格式
        • 输出格式
        • 数据范围
        • 输入样例:
        • 输出样例:
    • 思路和代码
  • 最低通行费
        • 输入格式
        • 输出格式
        • 数据范围
        • 输入样例:
        • 输出样例:
        • 样例解释
    • 思路和代码
  • 方格取数
    • 题目背景
    • 题目描述
    • 输入格式
    • 输出格式
    • 样例 #1
      • 样例输入 #1
      • 样例输出 #1
    • 提示
    • 思路和代码
  • 传纸条
  • [NOIP2008 提高组] 传纸条
    • 题目描述
    • 输入格式
    • 输出格式
    • 样例 #1
      • 样例输入 #1
      • 样例输出 #1
    • 提示
    • 思路和代码

摘花生

1015. 摘花生 - AcWing题库

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

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

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

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

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

在这里插入图片描述

输入格式

第一行是一个整数T,代表一共有多少组数据。

接下来是T组数据。

每组数据的第一行是两个整数,分别代表花生苗的行数R和列数 C。

每组数据的接下来R行数据,从北向南依次描述每行花生苗的情况。每行数据有C个整数,按从西向东的顺序描述了该行每株花生苗上的花生数目M。

输出格式

对每组输入数据,输出一行,内容为Hello Kitty能摘到得最多的花生颗数。

数据范围

1≤T≤100,
1≤R,C≤100,
0≤M≤1000

输入样例:
2
2 2
1 1
3 4
2 3
2 3 4
1 6 5
输出样例:
8
16

思路和代码

用f[i, j]表示从第1行第1列,到第i行第j列,路上最多能采集到的花生数量。

因为只能往下和往右走,因此f[i, j]只能从f[i - 1, j]和f[i, j - 1]转移过来。

因此,有:

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

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

const int N = 110;

int t, r, c;
int a[N][N];
int f[N][N];

int main() {
    cin >> t;
    while(t -- ) {
        cin >> r >> c;
        for(int i = 1; i <= r; i ++ ) {
            for(int j = 1; j <= c; j ++ ) {
                scanf("%d", &a[i][j]);
            }
        }
        
        memset(f, 0, sizeof f);
        
        for(int i = 1; i <= r; i ++ ) {
            for(int j = 1; j <= c; j ++ ) {
                f[i][j] = max(f[i - 1][j], f[i][j - 1]) + a[i][j];
            }
        }
        
        cout << f[r][c] << endl;
        
    }
    
    return 0;
}

最低通行费

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

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

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

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

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

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

请问至少需要多少费用?

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

输入格式

第一行是一个整数,表示正方形的宽度 N。

后面 N 行,每行 N 个不大于 100 的正整数,为网格上每个小方格的费用。

输出格式

输出一个整数,表示至少需要的费用。

数据范围

1≤N≤100

输入样例:
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

BASIC
输出样例:
109

TEXT
样例解释

样例中,最小值为 109=1+2+5+7+9+12+19+21+33。

思路和代码

用f[i, j]表示走到[i, j]的最小花销。“商人必须在 (2N−1) 个单位时间穿越出去。”表示只能向下或者向右走。这道题和上一道摘花生类似,不同之处是这道题求的是最小值。

状态转移方程:

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

初始化时,因为是求最小值,要注意边界时不能取到周围的值,所以把f初始化为0x3f。状态[1, 1]要从[0, 1]或者[1, 0]转移过来,所以把f[1, 0]或者f[0, 1]设为0.

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

const int N = 110;

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

int main() {
	cin >> n;
	
	memset(f, 0x3f, sizeof f);
	
	for(int i = 1; i <= n; i ++ ) {
		for(int j = 1; j <= n; j ++ ) {
			scanf("%d", &a[i][j]);
			f[i][j] = 0;
		}
	}
	
	f[0][1] = 0; 
	
	for(int i = 1; i <= n; i ++ ) {
		for(int j = 1; j <= n; j ++ ) {
			f[i][j] = min(f[i - 1][j], f[i][j - 1]) + a[i][j];
		}
	}
	
	cout << f[n][n] << endl;
	
	return 0;
}


方格取数

[P1004 NOIP2000 提高组] 方格取数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目背景

NOIP 2000 提高组 T4

题目描述

设有 N × N N \times N N×N 的方格图 ( N ≤ 9 ) (N \le 9) (N9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字 0 0 0。如下图所示(见样例):

在这里插入图片描述

某人从图的左上角的 A A A 点出发,可以向下行走,也可以向右走,直到到达右下角的 B B B 点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字 0 0 0)。
此人从 A A A 点到 B B B 点共走两次,试找出 2 2 2 条这样的路径,使得取得的数之和为最大。

输入格式

输入的第一行为一个整数 N N N(表示 N × N N \times N N×N 的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的 0 0 0 表示输入结束。

输出格式

只需输出一个整数,表示 2 2 2 条路径上取得的最大的和。

样例 #1

样例输入 #1

8
2 3 13
2 6  6
3 5  7
4 4 14
5 2 21
5 6  4
6 3 15
7 2 14
0 0  0

样例输出 #1

67

提示

数据范围: 1 ≤ N ≤ 9 1\le N\le 9 1N9

思路和代码

这道题和上面的题不同之处在于这道题是走两遍的,对于每一个格子,它上面的数字只能加一次。

假设同时走两条路,那么当第一条路走到的点[i1, j1]和第二条路走到的点[i2, j2]重合时,一定有i1 + j1 = i2 + j2.

我们设i1 + j1 = k = i2 + j2.那么k从2逐渐增加到2 * n.

设f[k, i1, i2]表示第一条路走到了点[i1, j1],第二条路走到了点[i2, j2],且i1 + j1 = k,f[k, i1, i2]表示取得的数之和的最大值。

f[k, i1, i2]可以从4个点转移过来:f[k - 1, i1, i2], f[k - 1, i1 - 1, i2], f[k - 1, i1, i2 - 1], f[k - 1, i1 - 1, i2 - 1]。即[i1, j1]是从[i1 - 1, j1]或者[i1, j1 - 1]转移过来的,[i2, j2]是从[i2 - 1, j2]或者[i2, j2 - 1]转移过来的,二者排列组合就得到了f[k, i1, i2]的转移方程。

f[k, i1, i2] = max(f[k - 1, i1 - 1, i2], f[k - 1, i1, i2 - 1], f[k - 1, i1, i2], f[k - 1, i1 - 1, i2 - 1]) + t。

其中t表示[i1, j1]和[i2, j2]两个点能取到的数。

#include<iostream>
#include<algorithm>
using namespace std;

const int N = 15;

int g[N][N];
int n;
int f[2 * N][N][N];

int main() {
    cin >> n;
    int a, b, c;
    while(cin >> a >> b >> c, a || b || c) {
        g[a][b] = c;
    }
    
    for(int k = 2; k <= 2 * n; k ++ ) {
        for(int i1 = 1; i1 <= n; i1 ++ ) {
            for(int i2 = 1; i2 <= n; i2 ++ ) {
                int t = g[i1][k - i1];
                if(i1 != i2) t += g[i2][k - i2];
                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);
            }
        }
    }
    
    cout << f[2 * n][n][n] << endl;
    return 0;
}

传纸条

[P1006 NOIP2008 提高组] 传纸条 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

[NOIP2008 提高组] 传纸条

题目描述

小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题。一次素质拓展活动中,班上同学安排坐成一个 m m m n n n 列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了。幸运的是,他们可以通过传纸条来进行交流。纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,坐标 ( 1 , 1 ) (1,1) (1,1),小轩坐在矩阵的右下角,坐标 ( m , n ) (m,n) (m,n)。从小渊传到小轩的纸条只可以向下或者向右传递,从小轩传给小渊的纸条只可以向上或者向左传递。

在活动进行中,小渊希望给小轩传递一张纸条,同时希望小轩给他回复。班里每个同学都可以帮他们传递,但只会帮他们一次,也就是说如果此人在小渊递给小轩纸条的时候帮忙,那么在小轩递给小渊的时候就不会再帮忙。反之亦然。

还有一件事情需要注意,全班每个同学愿意帮忙的好感度有高有低(注意:小渊和小轩的好心程度没有定义,输入时用 0 0 0 表示),可以用一个 [ 0 , 100 ] [0,100] [0,100] 内的自然数来表示,数越大表示越好心。小渊和小轩希望尽可能找好心程度高的同学来帮忙传纸条,即找到来回两条传递路径,使得这两条路径上同学的好心程度之和最大。现在,请你帮助小渊和小轩找到这样的两条路径。

输入格式

第一行有两个用空格隔开的整数 m m m n n n,表示班里有 m m m n n n 列。

接下来的 m m m 行是一个 m × n m \times n m×n 的矩阵,矩阵中第 i i i j j j 列的整数表示坐在第 i i i j j j 列的学生的好心程度。每行的 n n n 个整数之间用空格隔开。

输出格式

输出文件共一行一个整数,表示来回两条路上参与传递纸条的学生的好心程度之和的最大值。

样例 #1

样例输入 #1

3 3
0 3 9
2 8 5
5 7 0

样例输出 #1

34

提示

【数据范围】

对于 30 % 30\% 30% 的数据,满足 1 ≤ m , n ≤ 10 1 \le m,n \le 10 1m,n10
对于 100 % 100\% 100% 的数据,满足 1 ≤ m , n ≤ 50 1 \le m,n \le 50 1m,n50

【题目来源】

NOIP 2008 提高组第三题。

思路和代码

这道题和方格取数很相似,用方格取数的思路也能做。它和方格取数的不同点在于它不能经过同一个点两次。但是注意,每个点的值都是正数,它的最优解一定不可能经过一个点两次。证明链接:AcWing 275. 证明传纸条为何可以使用方格取数的代码 - AcWing

另外需要注意i1和i2的取值范围,它不能超过行数m且不能超过k。

#include<iostream>
using namespace std;

const int N = 60;

int g[N][N];
int n, m;
int f[2 * N][N][N];

int main() {
    cin >> m >> n;
    
    for(int i = 1; i <= m; i ++ ) 
        for(int j = 1; j <= n; j ++ ) 
            scanf("%d", &g[i][j]);
    
    for(int k = 2; k <= m + n; k ++ ) {
        for(int i1 = 1; i1 <= m && i1 < k; i1 ++ ) {
            for(int i2 = 1; i2 <= m && i2 < k; i2 ++ ) {
                int t = g[i1][k - i1];
                if(i1 != i2) t += g[i2][k - i2];
                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);
			}
        }
    }
    
    cout << f[n + m][m][m] << endl;
    return 0;
    
}

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

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

相关文章

minikube 实践练习4 - 滚动更新

1. 应用版本更新 #查看image kubectl describe pods#设置应用的image为新版本 v1 -> v2 kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcampdocker.io/jocatalin/kubernetes-bootcamp:v2#验证更新结果 export NODE_PORT"$(kubectl get services/…

在Moodle中集成ONLYOFFICE:学习管理+文档功能全面指南

一、引言 随着在线教育的发展&#xff0c;Moodle作为领先的开源学习管理系统&#xff0c;其灵活性和可扩展性为教育工作者提供了丰富的功能。而ONLYOFFICE文档服务器的加入&#xff0c;更是为Moodle用户带来了无缝的文档处理与协作体验。本文将详细指导您如何在Moodle中深度集成…

【数据结构】二叉树篇

文章目录 1.二叉树链式结构功能的实现1.1 前置说明1.2 二叉树的遍历1.2.1 前序、中序以及后序遍历1.2.2 层序遍历 1.3 节点个数以及高度差1.3.1 二叉树的节点个数1.3.2 二叉树叶子节点个数1.3.3 二叉树第K层节点个数1.3.4 二叉树树查找值为x的节点1.3.5 二叉树的销毁 1.4 代码整…

RAG 工具和框架介绍: Haystack、 LangChain 和 LlamaIndex

Haystack、 LangChain 和 LlamaIndex&#xff0c;以及这些工具是如何让我们轻松地构建 RAG 应用程序的&#xff1f; 我们将重点关注以下内容&#xff1a; HaystackLangChainLlamaIndex 增强LLM 那么&#xff0c;为什么会有这些工具存在呢&#xff1f;如你所知&#xff0c;C…

LVS学习与练习

LVS (Linux Virtual Server) 是一种高性能的负载均衡解决方案&#xff0c;它基于 Linux 内核实现。LVS 可以用来构建高可用性和高性能的 Web 服务器集群。LVS 支持多种负载均衡算法和模式&#xff0c;可以有效地分发网络请求到多台后端服务器上。 LVS 的主要组成部分 1. Direc…

InternLM+LlamaIndex RAG 实践

本期实战训练营介绍了使用书生葡语的InternLM和LlamaIndex框架进行RAG项目的实践。内容分为三个部分&#xff1a;回顾InternLM的发展历程&#xff0c;介绍RAG的基本概念和应用&#xff0c;以及实践一个RAG项目。RAG技术结合了检索与生成&#xff0c;通过外部知识库增强大模型的…

开源Docker图形化管理工具DockerUI

DockerUI 是一个 Web 用户界面&#xff0c;它允许用户通过浏览器与 Docker 守护进程进行交互&#xff0c;而无需在命令行中执行 Docker 命令。它为 Docker 容器、镜像、网络等提供了直观的图形界面管理。然而&#xff0c;需要注意的是&#xff0c;DockerUI 已经不再是最流行的 …

领先数年!这款ERP系统已成制造业趋势!

企业数字化转型的趋势不可阻挡&#xff0c;在全球化竞争的背景下&#xff0c;市场变化迅速&#xff0c;客户需求日益多样化&#xff0c;企业需要更加敏捷地响应市场变化&#xff0c;提高生产效率和产品质量&#xff0c;以满足客户的需求。 而在这一转型过程中&#xff0c;ERP …

怎么直接在PDF上修改内容?随心编辑PDF内容

PDF(Portable Document Format)作为一种专用于阅读而非编辑的文档格式&#xff0c;其设计的核心目的是保持文档格式的一致性&#xff0c;确保文档在不同平台和设备上都能以相同的布局和格式呈现。然而&#xff0c;在实际工作和生活中&#xff0c;我们经常需要对PDF文档进行编辑…

Python编写Word文档

目录 1. 创建word文档 2. 添加标题、居中、字体16大小 3. 添加标题一 4. 添加一段话并设置字体颜色 5. 换页 6. 插入表格 1. 创建word文档 from docx import Documentdoc Document() 2. 添加标题、居中、字体16大小 from docx.shared import Pt from docx.enum.text i…

AT360-6T杭州中科微授时模块场景应用

AT360-6T是一款高性能多系统卫星定位授时模块&#xff0c;基于自主研发的北斗多系统 SOC 芯片&#xff0c;可以同时接收中国的 BDS(北斗二号和北斗三号)、美国的 GPS、俄罗斯的 GLONASS、欧盟的 GALILEO 和日本的 QZSS 等多个卫星导航系统的 GNSS 信号来实现多系统联合定位授时…

实用篇 | 服务器查看监听端口的程序

对于一些程序员最痛苦的是接手一些“二手系统“&#xff0c; 由于年久失修&#xff0c; 加上裁员离职&#xff0c;系统文档不完善等原因&#xff0c; 只留下服务器配置和代码。 接手人&#xff0c;只能对着这些仅存的代码和服务器硬刚&#xff0c; 对服务器硬刚的第一步&#x…

高盛推荐包装食品行业两大首选股票

市场动荡与食品行业的防御性 近期市场的剧烈波动、7月份疲弱的就业报告以及对美联储可能降息的预期&#xff0c;引发了人们对经济衰退的担忧。尽管市场在本周有所反弹&#xff0c;投资者们开始调整策略&#xff0c;寻求更具防御性的投资方向。在这种背景下&#xff0c;包装食品…

Vue2移动端(H5项目)项目基于vant实现select单选(支持搜索、回显、自定义下拉label展示功能)

一 最终效果 二、参数配置 1、代码示例&#xff1a; <t-selectv-model"formData.materialNo"valueKey"materialNo"showLabel"materialName"labelKey"label"label"判定品级"input-align"right"placeholder&qu…

Google Earth Engine(GEE)——1986-2021年黄河入海口区域的逐年影像展示案例分析,并加载可以分享的URL链接

函数: size() Returns the number of elements in the collection. 返回集合中元素的数量。 Arguments: this:collection (FeatureCollection): The collection to count. Returns: Integer 融合影像可以一个接一个进行融合 merge(collection2) Merges two image co…

CAXA快捷键

1.左下角处选择导航&#xff0c;快捷键F6可以切换 2.自定义快捷键 鼠标右键点击菜单栏空白处 点击自定义&#xff0c;便可以修改快捷键

Leetcode—1239. 串联字符串的最大长度【中等】(unordered_set)

2024每日刷题&#xff08;155&#xff09; Leetcode—1239. 串联字符串的最大长度 实现代码 class Solution { public:bool charSet(string & s) {unordered_set<char> charSet(s.begin(), s.end());// true表示有重复// false表示唯一return s.size() ! charSet.s…

HTML原生手搓询盘

效果展示&#xff1a; 1、PC布局&#xff1a; 2、移动布局&#xff1a; 3、交互展示&#xff1a; 1、HTML代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"wid…

鸿蒙学习(一):基础知识

认识和存储数据 基础类型&#xff1a; 数字&#xff1a;number 布尔值&#xff1a;boolean 变量存储&#xff1a; let 变量名&#xff1a;类型 值 let title:string 你好 注意&#xff1a;1、字符串需要引号引起来&#xff1b;2、单引号双引号都可以&#xff1b;3、存储的内…

高校如何利用AIGC提高教学效率?

AIGC技术可按照模态分为文本、图像、语言以及多模态等&#xff0c;其中以图像发展最为迅速&#xff0c;AI绘画技术深入广告设计、营销、工业设计、游戏设计等各个领域&#xff0c;复合增长率将超过80% &#xff0c;未来以内容生产模式变革为根本将引爆生产力革命。目前AI人才缺…