题目描述

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

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

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

输入格式

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

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

输出格式

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

题面是直接复制 的,有点炸,但是没关系(反正不会有人到位这里来看题面

我觉得这题的难点在于同时要找到两条路径,并且不能交叉,这个在dp里面是比较难进行限制和定义的
还有就是这种dp类型对我可能是第一次,比较陌生。
这个最简单的状态设计我都是看别人的。。。
设f[i][j][k][l]表示一条路径走到了[i][j],另一条走到了[k][l]时,最大的好感度之和
转移比较明显,就从前面的点转移过来就好了,但是转移的时候要保证不会走到两个重合的点,这样就保证了两个路径不相交。

时间复杂的O(n^4),n最大50,可以接受。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read() {
char c=getchar();int a=0,b=1;
for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;return a*b;
}
int f[51][51][51][51],n,m,a[51][51];
int main()
{
n=read();m=read();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
a[i][j]=read();
}
}
for(int i=0;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
for(int k=0;k<=n;k++)
{
for(int h=0;h<=m;h++)
{
if(i==0||j==0||k==0||h==0)
f[i][j][k][h]=-1145141919;
else
f[i][j][k][h]=0;
}
}
}
}
f[1][1][1][1]=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
for(int k=1;k<=n;k++)
{
for(int h=1;h<=m;h++)
{
if((i==k&&j==h))
continue;
f[i][j][k][h]=max(f[i][j][k][h],f[i-1][j][k-1][h]+a[i][j]+a[k][h]);
f[i][j][k][h]=max(f[i][j][k][h],f[i-1][j][k][h-1]+a[i][j]+a[k][h]);
f[i][j][k][h]=max(f[i][j][k][h],f[i][j-1][k-1][h]+a[i][j]+a[k][h]);
f[i][j][k][h]=max(f[i][j][k][h],f[i][j-1][k][h-1]+a[i][j]+a[k][h]);
}
}
}
}
cout<<max(f[n-1][m][n-1][m],max(f[n-1][m][n][m-1],max(f[n][m-1][n-1][m],f[n][m-1][n][m-1])))<<endl;
return 0;
}

很奇怪,如果我尝试把结果直接转移到f[n][m][n][m]上然后输出,就会错,目前认为是我上面转移边界判断写错了
懒得找了

可以发现,其实这个4维数组里面是大部分用不上的,意思就是,我们浪费了非常多的空间和时间复杂度给了不可能的情况,因为我们每一次都是两边走一步
所以很容易可以发现,类似f[1][1][n][m]这样的状态是不可能也不存在也无意义的,但是它们的存在占用了大量转移的时间和空间
可以考虑优化考虑这一类无意义转移的特征
我们的转移都是一次性走两步的,很明显,这样的情况才是我们真正要的。
我们一次走一步,其实走的总步数就是曼哈顿距离,很明显,两条路的走的步数是一样的。
所以当两边同时走的时候,需要我们转移的地方很明显是没有那么多的,只有步数一样的两个点的状态,我们的转移才是有意义的,否则这个计算其实是没有任何作用的。
所以,我们可以增加一个状态,步数i,另外两个状态就是两个路径的竖直位置。
因为我们每次总是向下和向右走,所以通过步数和竖直位置可以直接计算出来它的水平距离。
这样那些多余的计算和空间就被优化掉了。

代码我懒得写了,主要是这个思考的方法
首先,这个优化依旧是从这个问题的特质出发的,我们发现了两边的步数i是一样的
(应该是我一开始就看的是别人的题解的原因,我感觉如果让我来设计状态,我不会这么暴力)
所以没有其次了(因为我感觉没必要)

然后就是这个问题的一个转化
我们把回传的问题转化为了从上往下的第二条路径。
这个是十分重要的,如果是先找到第一条,再去找第二条,时间复杂度会直接爆炸,而且不可做。
所以这个特性其实非常重要和有用的,因为正着麻烦,那就反着来,正难则反
而且利用这个,其实也是把不可相交这个要求的处理给简化, 一举两得,十分巧妙。。。

这应该就算是一道好题吧,比较的灵活

如果我比赛的时候遇到这个,我肯定是写不出来的

要怎么才能写出来呢?

1.发现这个特征,就是从下往上和从上往下是没有区别的

2.转化问题,把问题转化为找两个一起往下的路径(这个我想不到)

后面就比较简单了,我觉得这种转化其实也是dp的一个难点
只能靠积累了吧。。。
多积累,应该会在一定程度质变的。

加油

传纸条 luoguP1006的更多相关文章

  1. luoguP1006 传纸条

    题目描述 Description 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个 m" role="presentation& ...

  2. tyvj1011 传纸条

    背景 NOIP2008复赛提高组第三题 描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端, ...

  3. NOIP2008 传纸条

    题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运的是 ...

  4. NOIP2008传纸条[DP]

    题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运的是 ...

  5. NOIP2008 T3 传纸条 解题报告——S.B.S.

    题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运的是 ...

  6. [NOIP2008] 提高组 洛谷P1006 传纸条

    题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运的是 ...

  7. TYVJ 1011 NOIP 2008&&NOIP 2000 传纸条&&方格取数 Label:多线程dp

    做题记录:2016-08-15 15:47:07 背景 NOIP2008复赛提高组第三题 描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行 ...

  8. nyoj 61 传纸条

    点击打开链接 传纸条(一) 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做 ...

  9. P1011 传纸条//dp优化改进状态表示

    P1011 传纸条 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 NOIP2008复赛提高组第三题 描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不 ...

  10. Wikioi 1169 传纸条

    这道题是我人生第一道双线动规题,因此我觉得还是很有必要记录下来. 刚接触到这道题的时候我第一反应是单线的动规,可是下一秒我就觉得这样做可能会有问题,因为从左上角(以下简称A)到右下角(以下简称B)通过 ...

随机推荐

  1. 力扣744:寻找比目标字母大的最小字母; LeetCode744:Find Smallest Letter Greater Than Target

    题目见文末 LeetCode link 思路及题解 手写二分 源码: class Solution: def nextGreatestLetter(self, letters: List[str], ...

  2. EtherCAT 转CCLINK网关连接三菱plc应用案例

    EtherCAT 现场总线协议是由德国倍福公司在 2003 年提出的,该通讯协议拓扑结构十分灵活,数据传输速度快,同步特性好,可以形成各种网络拓扑结构. 捷米特JM-ECT-CCLK  是自主研发的一 ...

  3. Vue + Element ui 实现动态表单,包括新增行/删除行/动态表单验证/提交功能

    总结/朱季谦 最近通过Vue + Element ui实现了动态表单功能,该功能还包括了动态表单新增行.删除行.动态表单验证.动态表单提交功能,趁热打铁,将开发心得记录下来,方便以后再遇到类似功能时, ...

  4. bitfield

    bitfield 作用 位域修改 溢出控制 原理 通过对redis字符串二进制形式进行操作,通过改变其值的作用 更具体 将一个Redis字符串看作是一个由二进制位组成的数组. 并能对变长位宽和任意没有 ...

  5. Spring-Bean实例化三种的方式

    Bean实例化三种方式 无参构造实例化(重点) 工厂静态方法实例化 工厂实例方法实例化 工厂静态方法实例化 1.编写接口 package com.my; public interface UserDa ...

  6. <学习笔记> 关于二项式反演

    1 容斥原理的式子: \[|A1∪A2∪...∪An|=\sum_{1≤i≤n}|Ai|−\sum_{1≤i<j≤n}|Ai∩Aj|+...+(−1)^{n−1}×|A1∩A2∩...∩An| ...

  7. FlinkSQL类型系统

    类型有什么作用, 类型可以提供编译期检查, 避免到运行期才报错. 类型 首先Flink中自己定义了一套类型, 有LogicalType和DataType两个表示 LogicalType Logical ...

  8. [gin]数据解析和绑定

    前言 go version: 1.18 本文主要包含JSON.Form.Uri.XML的数据解析与绑定. JSON数据解析与绑定 go代码 package main import ( "ne ...

  9. 使用JDK自带工具调优JVM的常用命令

    前言 对于Java进程常见问题,可以通过JVM监控工具(比如Prometheus).Arthas等,或者使用JDK自带的工具.如果第三方监控工具线上没有的话,对jdk自带的工具就要多熟悉熟悉. 线上J ...

  10. IDEA使用@Autowired注解为什么会提示不建议?

    ​在使用IDEA编写Spring相关的项目时,当在字段上使用@Autowired注解时,总会出现一个波浪线提示:"Field injection is not recommended.&qu ...