Partition:一道 dp 神题,用到了以轮廓线的轨迹来做 dp 的技巧,和敲砖块这题的状态设计有点相似。

观察

首先观察样例,发现整张图可以看作是被两条线分隔开的。同时每个颜色的四个方向上又存在一大堆奇怪的性质,很容易发现这两条线一条是从左上到右下的线,另一条是从右下到左上的线。

暴力 dp

有了这两条线,并且发现这两条线一定不会往回走(比如往上走的线,不会在某个地方往下走),即无后效性,那么我们就可以暴力 dp 了。

设计 \(dp_{i,j,k}\) 表示在第 \(i\) 行时,两条线分别在第 \(j\) 列与第 \(k\) 列时的最大值。

然后暴力转移一下就好了,这种做法还要对两条线的位置关系进行分讨转移,比较麻烦,复杂度又高,因此我们需要从另一个角度考虑 dp。

正解

我们观察每个颜色各自的贡献,可以发现,红色的权值为 \(1\),且其他颜色的权值都比 \(1\) 大。因此我们可以把染色的过程看作先把每个数涂上红色,然后其他颜色的权值减小了 \(1\),再来 dp。

这样以后橙色的权值为 \(1\),黄色的权值为 \(2\),绿色的权值为 \(3\)。再来观察图的形态,可以发现橙色和绿色是连在一起的。所以我们可以把橙色和绿色的部分统一先填上色,过程就和上面暴力 dp 一样,从右上到左下进行 dp,只不过我们只需要维护一条线的路线,复杂度降低了很多。

从右上到左下具体的转移方程如下:

\[dp_{i,j}=\max(dp_{i-1,j}+f_{i,m}-f_{i,j-1},dp_{i,j+1}+a_{i,j})
\]

其中 \(f_{i,j}\) 表示第 \(i\) 行的前缀和数组,\(a_{i,j}\) 表示第 \(i\) 行第 \(j\) 列的元素。

最后黄色和绿色的权值都变成 \(2\) 了,因为他们两个依然是相邻的,所以我们可以从左上到右下做一次 dp,做最后一次涂色,统计进答案就好了。

一共做了两次 dp,时间复杂度为 \(O(nm)\)。

代码

在实现上我们在 dp 时可以多进行一次,这样统计答案时就不用一个一个取最大值,只需要取最后转移到的地方就好了。

#include <bits/stdc++.h>
#define fi first
#define se second
#define lc (p<<1)
#define rc ((p<<1)|1)
using namespace std;
typedef long long ll;
typedef pair<int,int> pi;
int n,m;
ll a[2005][2005],dp1[2005][2005],dp2[2005][2005],ans=0,f[2005][2005];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
ans+=a[i][j];
f[i][j]=f[i][j-1]+a[i][j];
}
}
memset(dp1,-0x3f,sizeof(dp1));
memset(dp2,-0x3f,sizeof(dp2));
for(int i=1;i<=m+1;i++)dp1[0][i]=dp2[0][i]=0;
for(int i=1;i<=n+1;i++)
{
for(int j=m+1;j>=1;j--)
{
dp1[i][j]=max(dp1[i-1][j]+f[i][m]-f[i][j-1],dp1[i][j+1]+a[i][j]);
}
for(int j=1;j<=m+1;j++)
{
dp2[i][j]=max(dp2[i-1][j]+f[i][j-1],dp2[i][j-1]+a[i][j-1]);
}
}
cout<<ans+dp1[n+1][1]+2*dp2[n+1][m+1];
return 0;
}

Luogu P10997 Partition 题解 [ 蓝 ] [ 分割线 dp ]的更多相关文章

  1. 【好好补题,因为没准题目还会再出第三遍!!】ACM字符串-组合数学(官方题解是数位DP来写)

    ACM字符串 .长度不能超过n .字符串中仅包含大写字母 .生成的字符串必须包含字符串“ACM”,ACM字符串要求连在一块! ok,是不是很简单?现在告诉你n的值,你来告诉我这样的字符串有多少个 输入 ...

  2. 题解 BZOJ1026 & luogu P2657 [SCOI2009]windy数 数位DP

    BZOJ & luogu 看到某大佬AC,本蒟蒻也决定学习一下玄学的数位$dp$ (以上是今年3月写的话(叫我鸽神$qwq$)) 思路:数位$DP$ 提交:2次 题解:(见代码) #inclu ...

  3. BZOJ 1003 物流运输 题解 【SPFA+DP】

    BZOJ 1003 物流运输 题解 Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的 ...

  4. Luogu P4643 【模板】动态dp

    题目链接 Luogu P4643 题解 猫锟在WC2018讲的黑科技--动态DP,就是一个画风正常的DP问题再加上一个动态修改操作,就像这道题一样.(这道题也是PPT中的例题) 动态DP的一个套路是把 ...

  5. Luogu P4643 【模板】动态dp(矩阵乘法,线段树,树链剖分)

    题面 给定一棵 \(n\) 个点的树,点带点权. 有 \(m\) 次操作,每次操作给定 \(x,y\) ,表示修改点 \(x\) 的权值为 \(y\) . 你需要在每次操作之后求出这棵树的最大权独立集 ...

  6. luogu P2657 [SCOI2009]windy数 数位dp 记忆化搜索

    题目链接 luogu P2657 [SCOI2009]windy数 题解 我有了一种所有数位dp都能用记忆话搜索水的错觉 代码 #include<cstdio> #include<a ...

  7. [NOIP10.3模拟赛]3.w题解--神奇树形DP

    题目链接: 咕 闲扯: 这题考场上把子任务都敲满了,5个namespace,400行11k 结果爆0了哈哈,因为写了个假快读只能读入一位数,所以手测数据都过了,交上去全TLE了 把边分成三类:0. 需 ...

  8. BZOJ 2669 Luogu P3160 [CQOI2012]局部极小值 (容斥原理、DP)

    题目链接 (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=2669 (luogu) https://www.luogu.org/prob ...

  9. 题解——洛谷P2734 游戏A Game 题解(区间DP)

    题面 题目背景 有如下一个双人游戏:N(2 <= N <= 100)个正整数的序列放在一个游戏平台上,游戏由玩家1开始,两人轮流从序列的任意一端取一个数,取数后该数字被去掉并累加到本玩家的 ...

  10. [BZOJ 1260][CQOI2007]涂色paint 题解(区间DP)

    [BZOJ 1260][CQOI2007]涂色paint Description 假设你有一条长度为5的木版,初始时没有涂过任何颜色.你希望把它的5个单位长度分别涂上红.绿.蓝.绿.红色,用一个长度为 ...

随机推荐

  1. 鸿蒙NEXT元服务:利用App Linking实现无缝跳转与二维码拉起

    [效果] 元服务链接格式(API>=12适用):https://hoas.drcn.agconnect.link/ggMRM 生成二维码后效果: ​ [参考网址] 使用App Linking实现 ...

  2. 面试官:来谈谈Vue3的provide和inject实现多级传递的原理

    前言 没有看过provide和inject函数源码的小伙伴可能觉得他们实现数据多级传递非常神秘,其实他的源码非常简单,这篇文章欧阳来讲讲provide和inject函数是如何实现数据多级传递的.ps: ...

  3. 12C++循环结构-for循环(2)

    一.循环变量为字符型 试编一程序,按字典顺序输出26个字母. 流程图: 程序代码如下: #include <iostream> //包含输入输出流头文件iostream using nam ...

  4. 【Python】【Flask】【字符串索引】计算人民币与美元的相互计算

    目录 简介 Python Code 导包 设置首页 计算的接口 问题0:设置请求方式 问题1:关于接收数据可能存在的问题 问题2:返回结果 启动 完整代码 HTML Code 问题分析 分析:获取下拉 ...

  5. Java代码打成jar后 classgetClassLoadergetResource("")返回为null

    用maven打成jar包后,Main.class.getClassLoader().getResource("")为null. 示例: public static void mai ...

  6. rocketMq4.2.0启动broker报错找不到或无法加载主类 Files\Java\jdk1.8.0_101\lib\dt.jar;C:\Program]

    假如弹出提示框提示'错误: 找不到或无法加载主类 xxxxxx'.打开runbroker.cmd,然后将'%CLASSPATH%'加上英文双引号.保存并重新执行start语句.做如下图处理 但是输出还 ...

  7. 使用Spring提供的BeanUtils.copyProperties()方法报错:Could not copy property 'xxx' from source to target

    使用Spring提供的BeanUtils.copyProperties()方法报错:Could not copy property 'xxx' from source to target; neste ...

  8. Qt编写地图综合应用54-动态点位标注

    一.前言 动态点位标注是定制的一个功能模块,提供直接地图上选点设置标记点,点位信息用结构体存储,其中包括了经度.纬度.速度.时间等信息,单击对应的标注点可以显示详细的弹框信息,弹框信息采用自定义的ht ...

  9. Qt音视频开发35-Onvif图片参数

    一.前言 视频中的图片的配置参数一般有亮度.饱和度.对比度.锐度等,以前一直以为这些需要通过厂家的私有协议SDK来设置才行,后面通过研究Onvif Device Manager 和 Onvif Dev ...

  10. 前端学习openLayers配合vue3(图层中心点的偏移)

    有了上一步的学习,我们知道了如何创建一个地图,现在我们来尝试更改一下图层的中心点 关键代码 let view = map.getView();//获取视图层 let center = view.get ...