【状态设计优化DP】P4310 绝世好题
状态 优化 设计 DP 好题
2023-09-11 14:14:52 时间
不愧是绝世好题
和abc那道E一样,也是重新定义状态来优化转移复杂度的DP
(56条消息) Atcoder Beginner Contest E - Work or Rest_lamentropetion的博客-CSDN博客
这种其实就是通过转移方式的特殊性来设计状态,从而降低复杂度
其实我感觉降低复杂度优化就是因为某个地方比较特殊,然后根据这个特殊性来优化
还有一点就是关于子序列的DP一般都以a[i]结尾来定义
这题是我做过的唯一线性DP设计状态的时候没加阶段的DP了,所以有点哈希内味
这种DP妙妙题我还没怎么写过,只会笨笨的那种DP,感觉得多写这种DP了
P4310 绝世好题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题意:
![](https://img-blog.csdnimg.cn/img_convert/747cbc7c9b21d2cbf246b135616f80fc.png)
思路:
首先就是每个人都会的暴力DP,像LIS那样,这样是n^2的,显然T飞了
我们来重新设计状态
考虑它的转移方式:当且仅当某一位两个数该位都是1时转移,因此我们定义dp[i]为最后一个数的第i位为1的最长长度
在加入某个数之前,我们遍历位统计出此时dp[i]的最大值
然后在加入这个数之后来转移
加入这个数之后,所有位都变成了那个统计出来的最大值+1,这样就转移好了
Code:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mxn=1e5+10;
int n;
int a[mxn],dp[32];
void solve(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++){
int mx=-1;
for(int j=30;j>=0;j--){
if((a[i]>>j)&1) mx=max(mx,dp[j]);
}
for(int j=30;j>=0;j--){
if((a[i]>>j)&1) dp[j]=max(dp[j],mx+1);
}
}
int mx=-1;
for(int j=30;j>=0;j--) mx=max(mx,dp[j]);
cout<<mx<<'\n';
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int __=1;//cin>>__;
while(__--)solve();return 0;
}
总结:
怎么去定义状态:
考虑转移方式,根据转移方式的特殊性来定义状态
这道题在设计状态时没有考虑阶段,所以有点哈希的感觉,我愿称之为哈希DP(bushi
还有一点就是关于子序列的DP一般都以a[i]结尾来定义
相关文章
- Vue+Express实现登录状态权限控制
- 有状态的 web 应用
- Flutter 陈航 10-状态 State 编程范式 构建过程
- java 15: jstat查看gc状态
- Android开发学习笔记(十四)横屏竖屏状态判断
- HTTP协议 结构,get post 区别-HTTP状态码(阿里)
- Cypress 等待某个 HTTP put 请求得到 200 状态码后,再执行下一步的操作代码
- HTTP状态码
- 一个好用的查看Angular应用ngrx状态的Chrome扩展:Redux devTools
- 【状态估计】基于增强数值稳定性的无迹卡尔曼滤波多机电力系统动态状态估计(Matlab代码实现)
- 数据库技术丨GaussDB(DWS)数据同步状态查看方法
- 前端如何获取http状态码400的返回值
- 很多time_await状态的端口出现
- Servlet HTTP 状态码
- 传输层 TCP连接管理 优化关闭连接时的TIME-WAIT状态