【DP合集】合并 union
2024-09-01 11:21:07
给出一个 1 ∼ N 的序列 A ( A 1 , A 2 , ..., A N ) 。你每次可以将两个相邻的元素合并,合并后的元素权值即为 这两个元素的权值之和。求将 A 变为一个非降序列,最少需要多少步操作。
Input
输入的第一行一个整数 N ( N ≤ 5000) 。
接下来一行 N 个整数,描述序列 A 。保证序列 A 中的每个元素的值不超过 1000 。
Output
输出一行一个整数,表示最少的操作数。
题解:
区间dp真的难,(。・∀・)ノ゙嗨!
好了,设dp[i][j]表示从区间把前j个数,把区间i~j合并后满足单调的元素数量,我们可以考虑,统计一个前缀和sum,然后枚举
三个端点i,j,k,我们是想把i~j压缩成一个数,然后k在i之前,找到元素数量最少的,进行转移,转移条件 是sum[i]-sum[k-1]<=sum[j]-sum[i]
代码:
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<cstring>
const int MAXN=;
using namespace std;
int dp[MAXN][MAXN],sum[MAXN],ans=-; void cl(){
memset(dp,,sizeof(dp));
memset(sum,,sizeof(sum));
} int main(){
cl();
int n;
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d",&sum[i]);
sum[i]+=sum[i-];
}
for(int i=;i<=n;i++){
dp[i][]=;
int k=i,res=-;
for(int j=i+;j<=n;j++){
while(k&&sum[i]-sum[k-]<=sum[j]-sum[i]) res=max(res,dp[i][k--]);
if(res==-) dp[j][i+]=-;
else dp[j][i+]=max(dp[j][i+],res+);
//printf("i=%d j=%d k=%d\n",i,j,k);
}
}
for(int i=;i<=n;i++) ans=max(ans,dp[n][i]);
if(ans==-) printf("-1");
else printf("%d",n-ans);
}
最新文章
- Linux2.6内核协议栈系列--TCP协议2.接收
- Azure 带宽
- List集合对象根据字段排序
- Difference Between Vector and Deque in C++
- pinyin4j使用示例
- URL特殊字符需转义
- margin-top塌陷
- vue的风格指南(必要的)
- vs2015官方下载链接
- 廖雪峰Java9正则表达式-2正则表达式进阶-3分组匹配
- 【LOJ#6280】数列分块4
- Codeforces 707E Garlands
- django admin后台设置
- 【Redis】使用Jedis操作Redis
- CentOS 7 系统root用户忘记密码的重置方法
- 在kali linux之下安装wps之后 报错字体缺失
- 了解dto概念,什么是DTO
- 日志工具——log4j
- react项目跨域问题
- Ceph添加/删除Mon(ceph.conf)
热门文章
- CentOS 7 下网络无法访问 Failed to start LSB: Bring up/.
- Sublime Text 实用方法
- ViewGroup和View
- 加入百度地图遇到 framework not found BaiduMapAPI***
- Spring入门(十二):Spring MVC使用讲解
- 为什么Kubernetes使用Pod作为最小调度单元
- 数据库占用CPU过高,性能分析与调优
- Redis数据库之服务器主从配置
- 升级@Scheduled-分布式定时任务
- mybatis collection和association使用区别