线性dp P1004 【方格取数】题解

代码比较简单的一题,重在思路(除非写假了)

传送门icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P1004

我的最初思路是两次二维dp,即贪心的取,用pre记录前一个位置,只有80pts,要是是在蓝桥拿分就可以跑路了(bushi)

代码如下

// Problem: 
//     P1004 [NOIP2000 提高组] 方格取数
//   
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1004
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)#include<iostream>
#include<cstring>
using namespace std;
const int N=10;
int ans=0;
int f[N][N];
int pre[N][N];//记录前一个位置
int val[N][N];int main(){int n;cin>>n;int a,b,c;while(cin>>a>>b>>c){if(a==0&&b==0&&c==0){break;}val[a][b]=c;}for(int i=1;i<=n;++i){for(int j=1;j<=n;++j){f[i][j]=max(f[i-1][j],f[i][j-1])+val[i][j];if(f[i-1][j]>=f[i][j-1]){pre[i][j]=1;//1从上一行来}else{pre[i][j]=2;//2从左边来}}}for(int i=1;i<=n;++i) pre[1][i]=2;for(int i=1;i<=n;++i) pre[i][1]=1;ans+=f[n][n];memset(f,0,sizeof f);int line=n;int rank=n;// for(int i=1;i<=n;++i){// for(int j=1;j<=n;++j){// cout<<val[i][j]<<' ';// }// cout<<endl;// }// cout<<endl;// for(int i=1;i<=n;++i){// for(int j=1;j<=n;++j){// cout<<pre[i][j]<<' ';// }// cout<<endl;// }val[rank][line]=0;while(rank>1||line>1){if(pre[rank][line]==1){rank-=1;}else{line-=1;}val[rank][line]=0;}for(int i=1;i<=n;++i){for(int j=1;j<=n;++j){f[i][j]=max(f[i-1][j],f[i][j-1])+val[i][j];}}// cout<<ans<<endl;ans+=f[n][n];cout<<ans<<endl;return 0;
}

这样子代码的问题在于,这道题两次要同时最优,并不能直接贪心

(或许是可以做的,但是要考虑的复杂情况比较多,本蒟蒻决定跳过)

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

例如这组数据,用上面的代码跑一下就会发现,不使用贪心(每次都取最大)的方法能获得更多的价值,于是,我们可以考虑使用一个四维dp来同时维护两次操作

// Problem: 
//     P1004 [NOIP2000 提高组] 方格取数
//   
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1004
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)#include<iostream>
#include<cstring>
using namespace std;
const int N=10;
int ans=0;
int f[N][N][N][N];
int val[N][N];int main(){int n;cin>>n;int a,b,c;while(cin>>a>>b>>c){if(a==0&&b==0&&c==0){break;}val[a][b]=c;}for(int i=1;i<=n;++i){for(int j=1;j<=n;++j){for(int k=1;k<=n;++k){for(int l=1;l<=n;++l){f[i][j][k][l]=max(max(f[i-1][j][k-1][l],f[i-1][j][k][l-1]),max(f[i][j-1][k-1][l],f[i][j-1][k][l-1]))+val[i][j]+val[k][l];if(i==k&&j==l) f[i][j][k][l]-=val[i][j];}}}}cout<<f[n][n][n][n]<<endl;return 0;
}

这里的四维也比较好理解,其实就是枚举了两种路线分别经过每一个点的状态,并且放在一起考虑(相等要减掉val[i][j])

另外:写二维的时候还没有明显的感觉,后面发现这不就是深搜变种嘛,洛谷有一题很像

本题数据是N<=9

但是我们有更好的三维优化   三维思路出处

思路:用k来表示x坐标和y坐标的和,然后通过y算出x坐标,创造一个f[k][y1​][y2​]来跑dp

和前面思路大致相同,有转移公式(思路,不是原代码)

f[k][i][j]=max(f[k−1][i][j],f[k−1][i−1][j],f[k−1][i][j−1],f[k−1][i−1][j−1])
+[(i==j)?map[k−i+1][i]:map[k−i+1][i]+map[k−j+1][j]]

其实这个方程不难理解,可以类似于用bfs的扩散来协助理解。枚举的k实际上就是步数,i,j就是枚举该不输的每个点。在这个dp公式中,如果i不动,k-1,那么其实就是行数-1,否则就是列数-1,巧妙的表现了两种情况。

感觉是很熟悉的优化,但是我想不到

代码如下:

// Problem: 
//     P1004 [NOIP2000 提高组] 方格取数
//   
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1004
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)#include<iostream>
#include<cstring>
using namespace std;
const int N=20;//数组最好开大一点,不然会越界(但是洛谷能过就是了)
int ans=0;
int f[N][N][N];
int val[N][N];int main(){int n;cin>>n;int a,b,c;while(cin>>a>>b>>c){if(a==0&&b==0&&c==0){break;}val[a][b]=c;}for(int k=2;k<=n*2;++k){//从2开始,不能从3,因为要考虑(1,1)的情况for(int i=1;i<=min(k-1,n);++i){//k-1  是因为要考虑横坐标至少有1for(int j=1;j<=min(k-1,n);++j){f[k][i][j]=max(max(f[k-1][i-1][j-1],f[k-1][i][j-1]),max(f[k-1][i-1][j],f[k-1][i][j]))+val[k-j][j]+val[k-i][i];if(i==j) f[k][i][j]-=val[k-i][i];//重复就减掉}}}cout<<f[n*2][n][n]<<endl;return 0;
}

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

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

相关文章

使用reduce递归获取有多层嵌套的数组中的children

常见的多层嵌套的数组&#xff0c;如下 const items [{id: 1,name: "item1",children: [{id: 11,name: "item11",children: [{id: 111, name: "item111"},{id: 112, name: "item112"}]},{id: 12,name: "item12",children:…

MySQL--优化(SQL语句执行慢,如何分析)

MySQL–优化&#xff08;SQL语句执行慢&#xff0c;如何分析&#xff09; 定位慢查询SQL执行计划索引 存储引擎索引底层数据结构聚簇和非聚簇索引索引创建原则索引失效场景 SQL优化经验 一、如何分析 聚合查询&#xff1a; 对于涉及大量数据的聚合操作&#xff0c;如果可能的…

【c++】STL--List的实现

目录 一. List的数据结构 二. List实现的基本框架 1. list的结点结构类 2. List的迭代器类 正向迭代器 反向迭代器 3. List操作接口的实现 1. 默认成员函数 构造函数 和 析构函数 拷贝构造函数 和 赋值运算符重载 2. 修改相关函数接口 insert 和 erase …

R语言简介、环境与基础语法及注释

R语言简介、环境与基础语法及注释 一、R语言1.R语言简介2.R语言官网3.R语言中国的镜像网站4.R语言下载5.R语言的历史 二、R语言环境1.Windows安装1.1 去 R 语言下载的镜像站点的列表下载1.2 选择版本进行下载1.3 点击运行1.4 一路默认&#xff0c;安装完毕&#xff01; 2.Linux…

【AI视野·今日Robot 机器人论文速览 第八十期】Fri, 1 Mar 2024

AI视野今日CS.Robotics 机器人学论文速览 Fri, 1 Mar 2024 Totally 32 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers Humanoid Locomotion as Next Token Prediction Authors Ilija Radosavovic, Bike Zhang, Baifeng Shi, Jathushan Rajasegaran…

ShardingSphere-SQL 解析 Issue 处理流程

ShardingSphere-SQL 解析 Issue 处理流程 这是之前给社区写的 SQL 解析 Issue 的处理流程&#xff0c;可以帮助社区用户快速参与到 ShardingSphere-SQL 解析任务当中。 ShardingSphere SQL 解析 issue 列表 Issue 背景说明 当前 Issue 使用自定义的爬虫脚本从对应的数据库官…

MySQL-----视图

一 视图 ▶ 介绍 视图view是一个虚拟表&#xff0c;非真实存在&#xff0c;其本质是根据SQL语句获取动态的数据集&#xff0c;并为其命名&#xff0c;用户使用时只需使用视图名称即可获取结果集&#xff0c;并可以将其当作表来使用。 数据库中存放了视图的定义&…

Java程序员修炼之道 之 Logging

1. 一个最基本的例子 使用Logging框架写Log基本上就三个步骤 引入loggerg类和logger工厂类 声明logger 记录日志 下面看一个例子 //1. 引入slf4j接口的Logger和LoggerFactory import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class UserService { //…

C#封装常用的Redis工具类

1.请先安装CSRedisCore 接口&#xff1a; namespace Tools.Redis {public interface IRedisTool{bool SetLongValue(string key, string value);bool SetValue(string key, string value, int outSecond);bool SetValue(string key, string value);bool Exists(string key);b…

企业数字人虚拟形象定制解决方案

随着数字化浪潮的推进&#xff0c;虚拟形象在各个领域都展现出了强大的潜力&#xff0c;美摄科技作为业界领先的数字人虚拟形象定制解决方案提供商&#xff0c;致力于为企业打造独一无二的虚拟形象&#xff0c;助力企业在数字世界中塑造独特的品牌形象。 一、解决方案概览 美…

02-prometheus监控-服务器节点监控node-exporter

一、概述 prometheus&#xff0c;本身是一个【数据收集】和【数据处理】的工具&#xff0c;如果效果要监控一台服务器物理机&#xff0c;有两种方式&#xff0c;一种是在物理机上部署“node-export”来收集数据上报给prometheus&#xff0c;另一种是“自定义监控”&#xff1b;…

SqlServer 默认值约束示例

创建表&#xff0c;创建时指定 money 字段默认值为0.00&#xff1b; create table t_24 ( account varchar(19) not null, id_card char(18) not null, name varchar(20) not null, money decimal(16,2) default 0.00 not null ); 录入2条记录&#xff0c;money字…

HTML极速入门

HTML基础 什么是HTML HTML(Hyper Text Markup Language),超文本标记语言. 超文本:比文本更强大.通过链接和交互式方式来组织和呈现信息的文本形式.不仅仅有文本,还可能包括图片,音频,或者自己经审阅过它的学者所加的评注,补充或脚注等. 标记语言:由标签构成的语言 HTML的标…

es6 相关面试题

1 var, let ,const 区别&#xff1f; 2 手写将对象进行合并 手写合并对象 3 普通函数和箭头函数区别&#xff1f; 4 find 和 filter的区别&#xff1f; 5 some和every区别&#xff1f;

ES核心概念(45-48)(56-62)(101-103)

ES集群 ES集群&#xff08;Cluster&#xff09;包含多个节点&#xff08;服务器&#xff09;&#xff0c;整体提供服务 核心概念 索引Index&#xff1a;类似于mysql中的表 映射Mapping:数据的结构信息 文档&#xff1a;相当于表中的一条记录 分片&#xff1a; 将数据分成多片…

java 面试题总结

1锁粗化和锁消除&#xff0c;锁膨胀和锁升级的区别。 https://www.cnblogs.com/xuxinstyle/p/13387778.html .无锁 < 偏向锁 < 轻量级锁 < 重量级锁 &#xff0c;说的时候不要忘记说无锁状态 2.Map 的实现&#xff0c;线程安全的实现 1、ConcurrentHashMap在JDK 1.7…

第五套CCF信息学奥赛c++练习题 CSP-J认证初级组 中小学信奥赛入门组初赛考前模拟冲刺题(阅读程序题)

第五套中小学信息学奥赛CSP-J考前冲刺题 二、阅读程序题 (程序输入不超过数组或字符串定义的范围&#xff0c;判断题正确填√错误填X;除特殊说明外&#xff0c;判断题 1.5分&#xff0c;选择题3分&#xff0c;共计40分) 第一题 递归函数 1 #include<iostream> 2 usin…

主要用于工控主板、工业控制器、程序烧录下载器、仿真器、新能源充电桩等众多涉及RS232通讯的产品——D3232

一、应用领域 D3232芯片主要用于工控主板、工业控制器、程序烧录下载器、仿真器、新能源充电桩等众多涉及RS232通讯的产品。 二、基本特性 D3232芯片由两个线路驱动器、两个线路接收器和双电荷泵电路组成&#xff0c;具有HBM>15kV、CDM>2kV的ESD保护能力&#xff0c;并且…

NLP_文本张量表示方法_2(代码示例)

目标 了解什么是文本张量表示及其作用.文本张量表示的几种方法及其实现. 1 文本张量表示 将一段文本使用张量进行表示&#xff0c;其中一般将词汇为表示成向量&#xff0c;称作词向量&#xff0c;再由各个词向量按顺序组成矩阵形成文本表示. ["人生", "该&q…

【力扣 - 盛最多水的容器】

题目描述 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明&#xff1a;你不能倾斜容…