$Luogu P2029$ 跳舞 题解
一道不是十分水的\(dp\).
首先我们考虑\(dp\)方程的构造。起初我定义的状态是\(dp_{i,j}\)表示前\(i\)个格子,总共跳了\(j\)次的最大得分。但事实上它并不可以转移,因为我们不知道新的一轮操作从之间的哪个格子算起。
那么状态转移方程就出来了,我们把第一维改成本次跳到第\(i\)个格子上,包括本次在内总共跳了\(j\)次的最大得分,那么转移的时候,由于本次一定要跳到\(i\)上(如状态中所定义),所以不用分类讨论。方程就是:$$dp_{i,j}=\max{dp_{k,j-1}-\rm{Sum(k + 1, i-1)}}+A_i$$
其中\(0 \leq k < i(\text{不能两次跳到同一个格子上所以右区间为开区间})\),\(\rm{Sum(l,r)}\mathcal{=\sum\limits_{i=l}^{r}A_i}\)
代码大概是这样\((\rm{30pts})\):
#include <cstdio>
#include <iostream>
#define MAXN 5010
using namespace std ; int i, j, k, Ans ;
int N, T, S[MAXN], dp[MAXN][MAXN], A[MAXN], B[MAXN] ;
int main(){
cin >> N >> T ;
for (i = 1 ; i <= N ; ++ i)
scanf("%d", &A[i]), S[i] = S[i - 1] + A[i] ;
for (i = 1 ; i <= N ; ++ i) scanf("%d", &B[i]) ;
for (i = 0 ; i <= N ; ++ i)
for (j = 0 ; j <= N ; ++ j)
dp[i][j] = -192608170 ; dp[0][0] = 0 ;
for (i = 1 ; i <= N ; ++ i)
for (j = 1 ; j <= i ; ++ j){
for (k = 0 ; k < i ; ++ k)
dp[i][j] = max(dp[i][j], dp[k][j - 1] - S[i - 1] + S[k] + A[i]) ;
if (j % T == 0) dp[i][j] += B[i] ; Ans = max(Ans, dp[i][j]) ;
}
cout << Ans << endl ; return 0 ;
}
但是我们发现,这个复杂度是\(\Theta(n^3)\)的,于是选择优化。\(dp\)优化的老套路就是:
优化状态维数
优化转移复杂度
而此处我们不可以优化状态了,所以考虑优化转移复杂度。转移的复杂度是\(\Theta(n)\)的,我们考虑可否\(\Theta(1)\)转移,最终使得总复杂度为\(\Theta(n^2) \times \Theta(1) \leq O(n^2)\)
从状态转移方程入手,我们发现有关于\(k\)是满足单调性的。所以不妨我们记录一下每次的\(k\),即把\(dp[k][j-1]+ S[k]\)中的最大值存储下来,从而达到\(\Theta(1)\)转移的目的。
此处笔者使用了比较玄学的存储方式……类似刷表……当然这个地方有多种的优化方式啦~
完整版\(code\)(700~800ms):
#include <cstdio>
#include <iostream>
#define MAXN 5010
using namespace std ; int i, j, k, p, Ans ;
int N, T, Last[MAXN], S[MAXN], dp[MAXN][MAXN], A[MAXN], B[MAXN] ;
int main(){
cin >> N >> T ;
for (i = 1 ; i <= N ; ++ i)
scanf("%d", &A[i]), S[i] = S[i - 1] + A[i] ;
for (i = 1 ; i <= N ; ++ i) scanf("%d", &B[i]) ;
for (i = 0 ; i <= N ; ++ i)
for (j = 0 ; j <= N ; ++ j)
dp[i][j] = -192608170 ; dp[0][0] = 0 ;
for (j = 1 ; j <= N ; ++ j){
for (i = j ; i <= N ; ++ i){
p = Last[i - j], Last[i - j] = 0 ;
dp[i][j] = p - S[i - 1] + A[i] ;
if (j % T == 0) dp[i][j] += B[i] ; Ans = max(Ans, dp[i][j]) ;
Last[i - j] = max(Last[i - j - 1], dp[i][j] + S[i]) ;
}
}
cout << Ans << endl ; return 0 ;
}
毒瘤常数优化后被艹到龟速的版本(1100ms +):
#include <cstdio>
#include <cstring>
#include <iostream>
#define max Max
#define MAXN 5010
#define Inf 19260817
using namespace std ; int i, j, k, p, t, Ans ;
int N, T, Last[MAXN], S[MAXN], dp[MAXN][MAXN], A[MAXN], B[MAXN] ;
inline int Max(int a, int b){
return a & ((b - a) >> 31) | b & ( ~ (b - a) >> 31) ;
}
inline int qr(){
int res = 0 ; char c = getchar() ;
while (!isdigit(c)) c = getchar() ;
while (isdigit(c)) res = (res << 1) + (res << 3) + c - 48, c = getchar() ;
return res ;
}
int main(){
cin >> N >> T ;
for (i = 0 ; i <= N ; ++ i)
for (j = 0 ; j <= N ; ++ j)
dp[i][j] = -Inf ; dp[0][0] = 0 ;
for (i = 1 ; i <= N ; ++ i)
A[i] = qr(), S[i] = S[i - 1] + A[i] ;
for (i = 1 ; i <= N ; ++ i) B[i] = qr() ;
for (j = 1 ; j <= N ; ++ j){
for (i = j ; i <= N ; ++ i){
t = i - j, p = Last[t], dp[i][j] = p - S[i - 1] + A[i] ;
if (!(j % T)) dp[i][j] += B[i] ; Ans = max(Ans, dp[i][j]), Last[t] = max(Last[t - 1], dp[i][j] + S[i]) ;
}
}
cout << Ans << endl ; return 0 ;
}
唉,先有常数后有天,反向优化\(Sun\)神仙啊
随机推荐
- php获取本月、上月、上上月、今日、昨日、上周的起始时间
// 本月起始时间: $begin_time = date ( "Y-m-d H:i:s", mktime ( 0, 0, 0, date ( "m" ), 1 ...
- OSGI企业应用开发(七)细说Blueprint & Gemini Blueprint(二)
上篇文章介绍了标准的Blueprint 规范与 Gemini Blueprint如何自定义Bean配置文件路径,本文接着上篇文章继续介绍Blueprint的使用. 一.Bean的配置 前面提到过,Ge ...
- FI配置步骤清单
1.定义公司代码 配置路径: R/3定制IMG的实施指南>企业结构>定义>财务会计>定义, 复制, 删除, 检查公司代码 事务代码 EC01 2.编辑科目表清单 配置路 ...
- 用php和ajax写一个省市区的三级联动,实现地区的下拉选择
要实现这个页面的三级联动,我们需要建立三个php文件,第一个php文件我们导入jQuery文件,里面嵌入JavaScript:第二个php文件我们做一个php的处理页面,里面引入我们封装好的数据库类文 ...
- 单表(SSM、SpringBoot、SpringCloud、Freemaker、BootStrap等)
山门也有门门道道, 开发.测试.安卓...... 小子被纳入MIS小山峰,虽不及BOP势力庞大,高手如云, 仅寥寥七人, 却也于入小山峰之事乐趣至极. 前几日峰主布下一道新手任务, 制作一张单表并运行 ...
- CSS 小结笔记之解决flex布局边框对不齐
在使用flex 进行伸缩布局的时候,经常会给子盒子设置边框,这时经常会出现上下边框对不齐的情况.本篇文章来探讨并解决这个问题. 具体出现的问题如下图所示 具体代码如下 <!DOCTYPE htm ...
- 《AngularJS权威教程》
第二章.数据绑定 2.2 简单的数据绑定 <!DOCTYPE html> <html ng-app> <head> <title>Simple app& ...
- 03-02_配置weblogic domain
配置Domain 图形化界面: [Windows] Windows菜单 [windows] config.cmd [Unix/Linux] config.sh 命令行界面: [windows] con ...
- [MySQL复制] SQL_ERROR 1032解决办法(non-gtid env)
一.缘由: 在主主同步的测试环境,由于业务侧没有遵循同一时间只写一个点的原则,造成A库上删除了一条数据,B库上在同时更新这条数据. 由于异步和网络延时,B的更新event先到达A端执行,造成A端找不到 ...
- Linux系统之TroubleShooting(启动故障排除)
尽管Linux系统非常强大,稳定,但是我们在使用过程当中,如果人为操作不当,仍然会影响系统,甚至可能使得系统无法开机,无法运行服务等等各种问题.那么这篇博文就总结一下一些常见的故障排除方法,但是不可能 ...