区间dp(入门题)
区间dp:顾名思义就是在区间上进行动态规划,通过合并小区间求解一段区间上的最优解。
常见模板:
for(int len=1;len<n;len++){//区间长度
for(int be=1;be+len<=n;be++){//起点
int en=be+len;//终点
for(int j=be;j<en;j++){//割点
dp[be][en]=min(dp[be][en],dp[be][j]+dp[j+1][en]+割点代价);(max也可以)
}
}
}
http://www.51nod.com/Challenge/Problem.html#!#problemId=1021
1021 石子归并
- 1 秒
- 131,072 KB
- 20 分
- 3 级题
收起
输入
第1行:N(2 <= N <= 100)
第2 - N + 1:N堆石子的数量(1 <= A[i] <= 10000)
输出
输出最小合并代价
输入样例
4
1
2
3
4
输出样例
19
解题思路:很明显割点代价为前缀和:sum【en】-sum【be-1】//en为该区间的终点,be为起点
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<stack>
#include<cstdio>
#include<map>
#include<set>
#include<string>
#include<queue>
using namespace std;
#define inf 0x3f3f3f3f
#define ri register int
typedef long long ll; inline ll gcd(ll i,ll j){
return j==0?i:gcd(j,i%j);
}
inline ll lcm(ll i,ll j){
return i/gcd(i,j)*j;
}
inline void output(int x){
if(x==0){putchar(48);return;}
int len=0,dg[20];
while(x>0){dg[++len]=x%10;x/=10;}
for(int i=len;i>=1;i--)putchar(dg[i]+48);
}
inline void read(int &x){
char ch=x=0;
int f=1;
while(!isdigit(ch)){
ch=getchar();
if(ch=='-'){
f=-1;
}
}
while(isdigit(ch))
x=x*10+ch-'0',ch=getchar();
x=x*f;
}
const int maxn=105;
ll dp[maxn][maxn];
ll sum[maxn];
ll a[maxn];
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%lld",&a[i]);
sum[i+1]=sum[i]+a[i];
}
for(int i=0;i<maxn;i++){
for(int j=0;j<maxn;j++){
dp[i][j]=1e18;
}
}
for(int i=0;i<maxn;i++){
dp[i][i]=0;
}
for(int len=1;len<n;len++){//区间长度
for(int be=1;be+len<=n;be++){//起点
int en=be+len;//终点
for(int j=be;j<en;j++){//割点
dp[be][en]=min(dp[be][en],dp[be][j]+dp[j+1][en]+sum[en]-sum[be-1]);
}
}
}
cout<<dp[1][n];
return 0;
}
四边形不等式优化:
我们可以知道,没有优化的区间dp时间复杂度为O(n^3),我们可以使用四边形不等式优化时间复杂度为O(n^2)。
这里直接给出四边形不等式的定理:
区间包含性:如果i<=j<m<=n,则满足w【j】【m】<=w【i】【n】
四边形不等式:如果i<=j<m<=n,满足w【i】【m】+w【j】【n】<=w【i】【n】+w【j】【m】(交叉小于包含)
我们假设w函数为割点代价同时满足区间包含性和四边形不等式,那么dp函数也满足四边形不等式。
我们定义m【i】【j】为dp【i】【j】取得最优解时候的割点的坐标
此时有:如果dp满足四边形不等式,有m【i】【j】<=m【i】【j+1】<=m【i+1】【j+1】
关于该定理的证明,有兴趣的可以看这篇博客:点击
接下来用四边形不等式来优化上一道题。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<stack>
#include<cstdio>
#include<map>
#include<set>
#include<string>
#include<queue>
using namespace std;
#define inf 0x3f3f3f3f
#define ri register int
typedef long long ll; inline ll gcd(ll i,ll j){
return j==0?i:gcd(j,i%j);
}
inline ll lcm(ll i,ll j){
return i/gcd(i,j)*j;
}
inline void output(int x){
if(x==0){putchar(48);return;}
int len=0,dg[20];
while(x>0){dg[++len]=x%10;x/=10;}
for(int i=len;i>=1;i--)putchar(dg[i]+48);
}
inline void read(int &x){
char ch=x=0;
int f=1;
while(!isdigit(ch)){
ch=getchar();
if(ch=='-'){
f=-1;
}
}
while(isdigit(ch))
x=x*10+ch-'0',ch=getchar();
x=x*f;
}
const int maxn=105;
ll dp[maxn][maxn];
ll sum[maxn];
ll a[maxn];
ll m[maxn][maxn];
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%lld",&a[i]);
sum[i+1]=sum[i]+a[i];
}
for(int i=0;i<maxn;i++){
for(int j=0;j<maxn;j++){
dp[i][j]=1e18;
}
}
for(int i=0;i<maxn;i++){
dp[i][i]=0;
m[i][i]=i;
}
for(int len=1;len<n;len++){//区间长度
for(int be=1;be+len<=n;be++){//起点
int en=be+len;//终点
for(int j=m[be][en-1];j<=m[be+1][en];j++){//割点 割点区间长度为en-be-1,dp区间为en-be,所以直接调用即可
// dp[be][en]=min(dp[be][en],dp[be][j]+dp[j+1][en]+sum[en]-sum[be-1]);
if(dp[be][en]>=(dp[be][j]+dp[j+1][en]+sum[en]-sum[be-1])){
dp[be][en]=dp[be][j]+dp[j+1][en]+sum[en]-sum[be-1];
m[be][en]=j;
}
}
}
}
cout<<dp[1][n];
return 0;
}
String painter
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7155 Accepted Submission(s): 3464
The first line contains string A.
The second line contains string B.
The length of both strings will not be greater than 100.
7
#include<stdio.h>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=;
int dp[maxn][maxn];
char ch[maxn],ch1[maxn];
int ss[maxn];
int main(){
while(~scanf("%s%s",ch+,ch1+)){
int len=strlen(ch+);
// printf("%s %s",ch+1,ch1+1);
memset(dp,,sizeof(dp));
for(int i=;i<=len;i++){
dp[i][i]=;
}
for(int l=;l<=len;l++){
for(int be=;be+l<=len;be++){
int en=be+l;
dp[be][en]=dp[be+][en]+;
for(int k=be+;k<=en;k++){
if(ch1[be]==ch1[k])dp[be][en]=min(dp[be+][k]+dp[k+][en],dp[be][en]);
}
}
}
for(int i=;i<=len;i++){
if(ch[i]==ch1[i])
ss[i]=ss[i-];
else{
ss[i]=dp[][i];
for(int k=;k<i;k++){
ss[i]=min(ss[i],ss[k]+dp[k+][i]);
}
}
}
// for(int i=1;i<=len;i++)
printf("%d\n",ss[len]);
}
return ;
}
区间dp(入门题)的更多相关文章
- poj 2955 区间dp入门题
第一道自己做出来的区间dp题,兴奋ing,虽然说这题并不难. 从后向前考虑: 状态转移方程:dp[i][j]=dp[i+1][j](i<=j<len); dp[i][j]=Max(dp[i ...
- [nyoj737]石子归并(区间dp入门题)
题意:有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆.求出总的代价最小值 ...
- 洛谷P2858 奶牛零食 题解 区间DP入门题
题目大意: 约翰经常给产奶量高的奶牛发特殊津贴,于是很快奶牛们拥有了大笔不知该怎么花的钱.为此,约翰购置了 \(N(1 \le N \le 2000)\) 份美味的零食来卖给奶牛们.每天约翰售出一份零 ...
- poj 3254 状压dp入门题
1.poj 3254 Corn Fields 状态压缩dp入门题 2.总结:二进制实在巧妙,以前从来没想过可以这样用. 题意:n行m列,1表示肥沃,0表示贫瘠,把牛放在肥沃处,要求所有牛不能相 ...
- 【dp入门题】【跟着14练dp吧...囧】
A HDU_2048 数塔 dp入门题——数塔问题:求路径的最大和: 状态方程: dp[i][j] = max(dp[i+1][j], dp[i+1][j+1])+a[i][j];dp[n][j] = ...
- POJ 2342 树形DP入门题
有一个大学的庆典晚会,想邀请一些在大学任职的人来參加,每一个人有自己的搞笑值,可是如今遇到一个问题就是假设两个人之间有直接的上下级关系,那么他们中仅仅能有一个来參加,求请来一部分人之后,搞笑值的最大是 ...
- 又一道区间DP的题 -- P3146 [USACO16OPEN]248
https://www.luogu.org/problemnew/show/P3146 一道区间dp的题,以区间长度为阶段; 但由于要处理相邻的问题,就变得有点麻烦; 最开始想了一个我知道有漏洞的方程 ...
- poj 2955 Brackets (区间dp基础题)
We give the following inductive definition of a “regular brackets” sequence: the empty sequence is a ...
- NYOJ 石子合并(一) 区间dp入门级别
描述 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆.求出总的代价 ...
- (树形DP入门题)Anniversary party(没有上司的舞会) HDU - 1520
题意: 有个公司要举行一场晚会.为了让到会的每个人不受他的直接上司约束而能玩得开心,公司领导决定:如果邀请了某个人,那么一定不会再邀请他的直接的上司,但该人的上司的上司,上司的上司的上司等都可以邀请. ...
随机推荐
- EL表达式取Map,List值的总结
EL表达式取Map中的值:后台action 中: Map map = new HashMap(); map.put(key1,value1); map.put(key2,value2); map.pu ...
- SQL中的排名函数(ROW_NUMBER、RANK、DENSE_RANK、NTILE)简介
排名函数是Sql Server2005新增的功能,下面简单介绍一下他们各自的用法和区别. 在使用排名函数的时候需要注意以下三点: 1.排名函数必须有 OVER 子句. 2.排名函数必须有包含 ORDE ...
- udt的java实现
udt协议是什么? 我就不回答了,可以网上搜索,一直都是c++的,java的实现已经很久没有修改了 经过测试,java版本有些一问题,现在已经将其修复,已经上传到csdn 另外自己根据实际的应用,再次 ...
- Spring NoSuchBeanDefinitionException原因分析
摘要:摘要:本文译自EugenParaschiv文章SpringNoSuchBeanDefinitionException原文链接:/2014th7cj/d/file/p/20161012/dv5o0 ...
- jQuery 正则数字验证、’Money验证、电话号码验证、身份证验证、邮箱验证、网址验证、敏感字符验证
jQuery只能输入数字 第一种写法: <input onkeyup="value=value.replace(/[^\d]/g,'')" /> 第二种写法: < ...
- JAVA REENTRANTLOCK、SEMAPHORE 的实现与 AQS 框架
引言 ReentrantLock是JDK提供的一个可重入互斥锁,所谓可重入就是同一个锁允许被已经获得该锁的线程重新获得.可重入锁的好处可以在递归算法中使用锁,不可重入锁则导致无法在递归算法中使用锁.因 ...
- 2018-2019-2 20165205 《网络对抗技术》 Exp1 PC平台逆向破解
2018-2019-2 20165205 <网络对抗技术> Exp1 PC平台逆向破解 1. 实验任务 1.1实验概括 用一个pwn1文件. 该程序正常执行流程是:main调用foo函数, ...
- jinja2 把文本变成html
data 是传过去的值 过滤器 | {{data.name | safe}}
- python———day01
一.变量命名规则: 1,要有描述性: 2,变量名只能以 下划线,数字,字母组成,不可以有特殊符号和空格: 3,不能以中文为变量名(规范): 4,不能以数字开头: 5,保留字符(即关键字:如print ...
- Mac谷歌浏览器跨域
1.创建一个文件夹,这个文件夹是用来保存关闭安全策略后的用户信息的,名字可以随意取,位置也可以随意放,我用的是MyChromeDevUserData open -n /Applications/Goo ...