---
title: "传纸条"
created: 2025-11-28
tags:
- 算法
---
# 传纸条
## 题目 [传纸条](https://www.acwing.com/problem/content/description/277/)
![[image-0fb62fae.png]]
## 思路分析
好题 当赏
再见
怎么可能放弃 (2024.3.5.22:00——2024.3.6.00:30 拿下!)
膜拜铅笔哥%%%
y总视频讲错了
这题思路还是和上一题方格取数一样 都是把x1,y1 x2,y2 转变成n,x1,x2的状态表示
方格取数是从左上角出发两次到右下角 这题是左上角出发一次 右下角出发一次 可以把右下角往左上角走的那个情况调转一下方向 问题转变成上题一样的从左上角出发两次
还有一点不一样的是 之前是可以走重复的点 只不过只取一次的价值 这次变成了一定不能走重复的点 emm 但其实选出来的方案就是不会经过同一个点的
可以完全套用上题的写法
至于为什么最优解法不会经过同一个点(上题可以走重复实际也没走重复)
有以下证明:(看看得了)
**情况一:最优解的两条路线是相互交叉经过的**
![[image-df8f608f.png]]
则我们可以对交叉出来的部分进行路线交换,如下图的操作
![[image-95d59e84.png]]
于是,我们可以发现,所有的交叉路线都会映射成一种一条路线只在下方走,一条路线只在上方走的不交叉路线
因此我们只需集中解决情况二即可
**情况二:最优解的两条路线不交叉,但在某些点有重合**
![[image-80d91c02.png]]
由于方格取数,对于走到相同格子时,只会累加一次格子的价值
于是我们可以使用贪心中的微调法来进行这部分的证明
对于重合的格子,我们必然可以在两条路线中找到额外的一条或两条路线,使得新的路线不发生重合
具体参照下图:
![[image-8e08d6da.png]]
由于原路线是最优解,则必然 wA=wB=0,则最优解路线必然是经过 A或 B的
因此,我们可以通过微调其中的一条路线,使之不经过重合点 C,同时路线的总价值没有减少
得证:最优解路线可以是不经过重复路线的
另外还有证明:
en 反正意思就是这题模型变得和上一题一模一样了 就好像最低通行费和摘花生一样 多了一个可以往上和往左的选择 但是证明后根本不会往左走 只会往右下走
问题变成一模一样的情况
这里就是一个 从左上到右下 走两次 的最大价值的模型
(不能走同一位置或同一位置只能取一次)
证明部分可以不管 知道选出来的答案路径就是不会重复选同一个格子就行了
核心就是 使用f[n][x1][x2]这样的三维状态表示代替f[x1][y1][x2][y2]的四维表示
n表示横纵坐标之和 在走的过程中 同一时刻两条路径的n是相同的
前置问题解决了
就是dp分析了
状态表示 f[k][i][j]
集合:路径长度为k,第一条路线到i,k-i位置,第二条路线到j,k-j位置的所有方案
属性:MAX
![[image-e69843a3.png]]
用v表示当前位置需要累加的价值
当x1≠x2,当前两条路线走到的格子不是同一个,v=w(i,k−i)+w(j,k−j) 当x1=x2,当前两条路线走到了同一个格子中,只需要累加一次
v=w(i,k−i)
右右
下右
右下 下下
状态计算: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]})+v;
这里有些乱 给一个理顺些的版本
![[image-cf0ebae3.png]]
## 代码实现
```cpp
#include
using namespace std;
const int N = 55, M = 2 * N;
int n, m;
int w[N][N];
int f[M][N][N];
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; ++ i)
{
for (int j = 1; j <= m; ++ j)
{
cin >> w[i][j];
}
}
for (int k = 2; k <= n + m; ++ k)
{
for (int i = 1; i < k && i <= n; ++ i)
{
for (int j = 1; j < k && j <= n; ++ j)
{
int v = w[i][k - i];
if (i != j) //判断两条路线是否经过同一个格子 经过的话只需要累加一次
v += w[j][k - j];
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]})+v;
}
}
}
cout << f[n + m][n][n] << endl;
return 0;
}
```
## 同类题型
## 视频讲解
---
⬅️ [[简单DP相关模型|简单DP相关模型]] 🏠 [[00-刷题理模型]] ➡️ [[摘花生|摘花生]]