当前位置: 首页 > news >正文

信息学奥赛一本通 1853:【08NOIP提高组】传纸条 | 洛谷 P1006 [NOIP 2008 提高组] 传纸条

【题目链接】

ybt 1853:【08NOIP提高组】传纸条
洛谷 P1006 [NOIP 2008 提高组] 传纸条

【题目考点】

1. 动态规划:坐标型动态规划

【解题思路】

抽象问题,存在m乘n的网格,每个格子中有一个数值,即同学愿意帮忙的好心程度。问(1,1)走到(m,n)是第一条路径,从(m,n)到(1,1)是第二条路径,两条路径不相交(即不存在格子同时属于两条路径)。
对于每个可能的从(m,n)到(1,1)的路径,都存在一个从(1,1)到(m,n)的与该路径经过相同格子的路径与其对应。
因此可以认为求的第二条路径也是从(1,1)走到(m,n)的路径。

1. 状态定义
  • 阶段:第一趟走到的位置(i,j)与第二趟走到的位置(k,l)
  • 决策:下一步如何走
  • 策略:第一趟从(1,1)走到(i,j),第二趟从(1,1)走到(k,l)的路径。
  • 策略集合:第一趟从(1,1)走到(i,j),第二趟从(1,1)走到(k,l)的所有路径方案。
  • 条件:取到的数字加和最大
  • 统计量:数字加和
    状态定义 d p i , j , k , l dp_{i,j,k,l} dpi,j,k,l:第一趟从(1,1)走到(i,j),第二趟从(1,1)走到(k,l)取到的数字加和最大的路径方案的数字加和。
2. 状态转移方程

记: a i , j a_{i,j} ai,j为(i,j)位置的数字。

  • 策略集合:从(1,1)走到(i,j),再从(1,1)走到(k,l)的路径方案
  • 分割策略集合:根据最后一步如何走到(i,j),以及如何走到(k,l)分割策略集合

由于每次只能向右或下走,那么第一趟走到(i,j)前,只可能在(i,j)上面一格(i-1,j)或左侧一格(i,j-1)。同理,第二趟走到(k,l)前,只可能在(k-1,l)或(k,l-1)。
因此,第一趟到达(i,j)前的位置与第二趟到达(k,l)前的位置就有4种组合:

  • (i-1,j)与(k-1,l)
  • (i,j-1)与(k-1,l)
  • (i-1,j)与(k,l-1)
  • (i,j-1)与(k,l-1)

先求出第一趟到达(i,j)前的位置与第二趟到达(k,l)前的位置的路线上的数字加和。
如果(i,j)与(k,l)不是同一位置,路径上数值加和就加上 a i , j a_{i,j} ai,j a k , l a_{k,l} ak,l
如果(i,j)与(k,l)是同一位置,两条路径经过了相同的位置,即两条路径相交。而题目要求两条路径不能相交,因此这种情况是不合法的。
我们可以通过设状态值,让这种不合法的情况不影响状态转移方程的计算。
由于接下来要求的是路径上数值加和的最大值,我们可以将此时的状态值设为一个很小的值(如-INF,const int INF = 0x3f3f3f3f)。如此一来,不合法的状态一定不会在求其它状态时使用。

详细情况如下:
如果如果(i,j)与(k,l)是同一位置:
如果(i,j)与(k,l)都是(1,1),那么 d p i , j , k , l dp_{i,j,k,l} dpi,j,k,l就是0。
如果(i,j)与(k,l)都是(m,n),那么可以是

  • 第一趟到达(m-1,n)后到达(m,n),第二趟到达(m,n-1)后到达(m,n),数字加和为 d p i , j , k , l = d p m − 1 , n , m , n − 1 dp_{i,j,k,l}=dp_{m-1,n,m,n-1} dpi,j,k,l=dpm1,n,m,n1
  • 第一趟到达(m,n-1)后到达(m,n),第二趟到达(m-1,n)后到达(m,n),数字加和为 d p i , j , k , l = d p m , n − 1 , m − 1 , n dp_{i,j,k,l}=dp_{m,n-1,m-1,n} dpi,j,k,l=dpm,n1,m1,n
  • 以上两种情况取最大值

对于其它情况,将状态设为一个很小的值, d p i , j , k , l = − I N F dp_{i,j,k,l}=-INF dpi,j,k,l=INF

如果(i,j)与(k,l)不是同一位置,或:

  • 第一趟到达(i-1,j)后到达(i,j),第二趟到达(k-1,l)后到达(k,l),数字加和为 d p i − 1 , j , k − 1 , l + a i , j + a k , l dp_{i-1,j,k-1,l}+a_{i,j}+a_{k,l} dpi1,j,k1,l+ai,j+ak,l
  • 第一趟到达(i,j-1)后到达(i,j),第二趟到达(k-1,l)后到达(k,l),数字加和为 d p i − 1 , j , k , l − 1 + a i , j + a k , l dp_{i-1,j,k,l-1}+a_{i,j}+a_{k,l} dpi1,j,k,l1+ai,j+ak,l
  • 第一趟到达(i-1,j)后到达(i,j),第二趟到达(k,l-1)后到达(k,l),数字加和为 d p i , j − 1 , k − 1 , l + a i , j + a k , l dp_{i,j-1,k-1,l}+a_{i,j}+a_{k,l} dpi,j1,k1,l+ai,j+ak,l
  • 第一趟到达(i,j-1)后到达(i,j),第二趟到达(k,l-1)后到达(k,l),数字加和为 d p i , j − 1 , k , l − 1 + a i , j + a k , l dp_{i,j-1,k,l-1}+a_{i,j}+a_{k,l} dpi,j1,k,l1+ai,j+ak,l
  • 以上四种情况取最大值。

状态转移方程为:
d p i , j , k , l = m a x { d p i − 1 , j , k − 1 , l , d p i − 1 , j , k , l − 1 , d p i , j − 1 , k − 1 , l , d p i , j − 1 , k , l − 1 } + a i , j + a k , l dp_{i,j,k,l}=max\{dp_{i-1,j,k-1,l},dp_{i-1,j,k,l-1},dp_{i,j-1,k-1,l},dp_{i,j-1,k,l-1}\}+a_{i,j}+a_{k,l} dpi,j,k,l=max{dpi1,j,k1,l,dpi1,j,k,l1,dpi,j1,k1,l,dpi,j1,k,l1}+ai,j+ak,l

观察状态转移方程可知,由于要在这4个状态 d p i − 1 , j , k − 1 , l , d p i − 1 , j , k , l − 1 , d p i , j − 1 , k − 1 , l , d p i , j − 1 , k , l − 1 dp_{i-1,j,k-1,l},dp_{i-1,j,k,l-1},dp_{i,j-1,k-1,l},dp_{i,j-1,k,l-1} dpi1,j,k1,l,dpi1,j,k,l1,dpi,j1,k1,l,dpi,j1,k,l1中求最大值。
只有 i = j 且 k = l i=j且k=l i=jk=l的状态 d p i , j , k , l dp_{i,j,k,l} dpi,j,k,l的值才是 − I N F -INF INF,因此以上4个状态的值不可能都是 − I N F -INF INF
因此如果其中某一状态的值为 − I N F -INF INF,则一定不会是数值最大的那个状态,不会影响 d p i , j , k , l dp_{i,j,k,l} dpi,j,k,l的计算结果。

观察该状态转移方程,在dp数组初值为0的情况下,当(i,j)与(k,l)都是(1,1)或(m,n)时,使用该状态转移方程也可以求出预期的值。

最终结果为第一趟从(1,1)到(m,n),第二趟从(1,1)到(m,n)的路径上能获取的最大的数字加和,即 d p m , n , m , n dp_{m,n,m,n} dpm,n,m,n

【题解代码】

  • 写法1:符合上述基本概念的写法
#include<bits/stdc++.h>
using namespace std;
#define N 55
#define INF 0x3f3f3f3f
int m, n, a[N][N], dp[N][N][N][N];//dp[i][j][k][l]:第一趟传到(i,j),第二趟传到(k,l)的所有路径中,权值加和最大的路径的权值加和 
int main()
{cin >> m >> n;for(int i = 1; i <= m; ++i)for(int j = 1; j <= n; ++j)cin >> a[i][j];for(int i = 1; i <= m; ++i)for(int j = 1; j <= n; ++j)for(int k = 1; k <= m; ++k)for(int l = 1; l <= n; ++l){if(i == k && j == l){if(i == 1 && j == 1)dp[i][j][k][l] = 0;else if(i == m && j == n)dp[i][j][k][l] = max(dp[m-1][n][m][n-1], dp[m][n-1][m-1][n]);elsedp[i][j][k][l] = -INF;}elsedp[i][j][k][l] = max(max(dp[i-1][j][k-1][l], dp[i-1][j][k][l-1]), max(dp[i][j-1][k-1][l], dp[i][j-1][k][l-1]))+a[i][j]+a[k][l];}cout << dp[m][n][m][n];return 0;
}
  • 写法2:使用状态转移方程求 i = 1 , j = 1 i=1,j=1 i=1,j=1 i = m , j = n i=m,j=n i=m,j=n的情况
#include<bits/stdc++.h>
using namespace std;
#define N 55
#define INF 0x3f3f3f3f
int m, n, a[N][N], dp[N][N][N][N];//dp[i][j][k][l]:第一趟传到(i,j),第二趟传到(k,l)的所有路径中,权值加和最大的路径的权值加和 
int main()
{cin >> m >> n;for(int i = 1; i <= m; ++i)for(int j = 1; j <= n; ++j)cin >> a[i][j];for(int i = 1; i <= m; ++i)for(int j = 1; j <= n; ++j)for(int k = 1; k <= m; ++k)for(int l = 1; l <= n; ++l){if(i == k && j == l && !(i == 1 && j == 1 || i == m && j == n))dp[i][j][k][l] = -INF;elsedp[i][j][k][l] = max(max(dp[i-1][j][k-1][l], dp[i-1][j][k][l-1]), max(dp[i][j-1][k-1][l], dp[i][j-1][k][l-1]))+a[i][j]+a[k][l];}cout << dp[m][n][m][n];return 0;
}

相关文章:

  • 宝塔安装的 MySQL 无法连接的情况及解决方案
  • ARM64虚拟地址到物理地址转换页表映射过程--基于crash
  • [测试_3] 生命周期 | Bug级别 | 测试流程 | 思考
  • 《国家高等教育智慧平台:重塑学习新时代》
  • MySQL Host 被封锁解决方案(全版本适用 + Java 后端优化)
  • 机器学习之随机森林(五)
  • vue3 el-table 行号
  • 鸿蒙进阶——驱动框架UHDF 机制核心源码解读(一)
  • 虚幻基础:摄像机
  • NHANES最新指标推荐:α-Klotho
  • 从微积分到集合论(1630-1910)(历史简介)——第2章——牛顿(Newton)和莱布尼兹(Neibniz)以及莱布尼兹传统(H.J.M.Bos)
  • 深入浅出Java-Lambda表达式
  • 「AR智慧应急」新时代:当AR眼镜遇上智能监控,打造立体化应急指挥系统
  • 14、自动配置【源码分析】-初始加载自动配置类
  • 【web全栈】若依框架B站学习视频:基础篇01-04
  • 洛谷P1226 【模板】快速幂
  • 【优秀三方库研读】在 quill 开源库 LogMarcos.h 中知识点汇总及讲解
  • 【flash】如何区分flash是哪家的
  • 基于51单片机的温湿度报警LCD1602液晶显示设计( proteus仿真+程序+设计报告+讲解视频)
  • 【Linux】了解 消息队列 system V信号量 IPC原理
  • 企业网站多大空间/百度统计代码
  • 做家具的外国网站/免费平台
  • 网站建设找超速云建站/百度优化排名软件
  • 是想建个网站 用本地做服务器/百度一下百度搜索网站
  • 网站开发绩效考核与薪酬/网站建设与管理属于什么专业