$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\)神仙啊
随机推荐
- 【 js 基础 】【读书笔记】Javascript “继承”
是时候写一写 “继承”了,为什么加引号,因为当你阅读完这篇文章,你会知道,说是 继承 其实是不准确的. 一.类1.传统的面向类的语言中的类:类/继承 描述了一种代码的组织结构形式.举个例子:“汽车”可 ...
- JavaScript--事件入门(24)
// JavaScript事件是由访问Web页面的用户引起的一系列操作; // 例如:用户点击;当用户执行某些操作的时候,再去执行一系列代码; 一 事件介绍 // 事件一般是用于浏览器和用户操作进行交 ...
- 网络基础 HTTP协议之http url简介
HTTP协议之http url简介 by:授客 QQ:1033553122 http url简介 http url通过http协议,用于定位网络资源,是一种特殊类型的URI(统一资源定位) http_ ...
- Android JNI的使用方法
1.JNI是什么 JNI是Java Native Interface的缩写,它提供若干的API实现Java与其他语言之间的通信.而Android Framework由基于Java语言的的Java层与基 ...
- 如何在 Azure 中自定义 Windows 虚拟机
若要以快速一致的方式配置虚拟机 (VM),通常需要某种形式的自动化. 自定义 Windows VM 的一种常用方法是使用适用于 Windows 的自定义脚本扩展. 本教程介绍如何执行下列操作: 使用自 ...
- Java语言的主要特点
Java语言有很多的优点,可靠.安全.编译和解释型语言.分布式.多线程.完全面向对象.与平台无关性等等. 与平台无关性 Java语言最大的优势在于与平台无关性,也就是可以跨平台使用. 绝大多数的编程语 ...
- Android高级_视频播放控件
一.Android系统自带VideoView控件 1. 创建步骤: (1)自带视频文件放入res/raw文件夹下: (2)声明初始化VideoView控件: (3)创建视频文件Uri路径,Uri调用p ...
- jQuery插件实例七:一棵Tree的生成史
在需要表示级联.层级的关系中,Tree作为最直观的表达方式常出现在组织架构.权限选择等层级关系中.典型的表现形试类似于: 一颗树的生成常常包括三个部分:1)数据库设计:2)后台程序:3)前端代码.那么 ...
- scss 使用
SCSS 常用功能 https://www.cnblogs.com/guangzan/p/10547335.html 定义变量$my-color: #666; //定义变量$my-heihgt: 10 ...
- XtraEditors六、ListBoxControl、CheckedListBoxControl、ImageListBoxControl
ListBoxControl 效果如下: 示例代码: string[] girlArr = { "面码", "Saber", "Mathilda&qu ...