区间dp的典例
区间dp, 属于dp的一种,顾名思义,便是对区间处理的dp,其中石子归并,括号匹配,整数划分最为典型。
(1)石子归并

dp三要素:阶段,状态,决策。
首先我们从第i堆石子到第j堆石子合并所花费的最小费用设为dp[i][j], 然后去想状态转移方程,dp[i][j]必然有两堆石子合并而来, 那么我们很快就可以推出状态转移方程为dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j] + s);(s为两堆石子的总和)
下面附上代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = + ;
int a[N], dp[N][N], n, sum[N]; void work(){
for(int l = ; l <= n; l ++){
for(int i = ; i + l <= n; i ++){
int j = i + l;
for(int k = i; k <= j; k ++){
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+][j] + sum[j] - sum[i-]);
}
}
}
printf("%d\n", dp[][n]);
} int main(){
while(scanf("%d", &n) == ){
memset(dp, 0x3f,sizeof(dp));
for(int i = ; i <= n; i ++){
scanf("%d", a + i);
sum[i] = sum[i-] + a[i];
dp[i][i] = ;
}
work();
}
return ;
}
当然还有变形题

思路差不多只不过把两个数的和改成积(ps:在处理前缀和的时候千万别取余,否则可能出现负数)
附上代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = + ;
int a[N], dp[N][N], n, ans, sum[N]; void work(){
for(int l = ; l <= n; l ++){
for(int i = ; i <= n - l + ; i ++){
int j = i + l - ;
for(int k = i; k < j; k ++){
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+][j] + ((sum[j] - sum[k])%)*((sum[k] - sum[i-])%));
}
}
}
printf("%d\n", dp[][n]);
} int main(){
while(scanf("%d", &n) == ){
for(int i = ; i <= n; i ++)
for(int j = ; j <= n; j ++)
dp[i][j] = ( << );
for(int i = ; i <= n; i ++){
scanf("%d", a + i);
sum[i] = sum[i-] + a[i];
dp[i][i] = ;
}
work();
}
return ;
}
(2)括号匹配

这题解释括号匹配的例题,只要找到这个字符串中括号最大匹配量t,就可以得出答案,设长度为l,则ans = l - t;
我们设dp[i][j] 为第i位到第j位最大的括号匹配量, 则他的转移方程为
dp[i][j] = max(dp[i][j], dp[i][k] + dp[k+1][j]);
当然如果第i位刚好与第j位刚好匹配
则dp[i][j] = dp[i+1][j-1] + 2;
下面附上代码
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std; string s; int n, dp[][]; int main(){
int T;
scanf("%d", &T);
while(T--){
cin >> s;
memset(dp, , sizeof(dp));
for(int l = ; l < s.size(); l ++){
for(int i = ; i + l < s.size(); i ++){
int j = i + l;
if(s[i] == '(' && s[j] == ')')
dp[i][j] = dp[i+][j-] + ;
if(s[i] == '[' && s[j] == ']')
dp[i][j] = dp[i+][j-] + ;
for(int k = i; k <= j; k ++){
dp[i][j] = max(dp[i][j], dp[i][k] + dp[k+][j]);
}
}
}
printf("%d\n", s.size() - dp[][s.size()-]);
}
return ;
}
(3)整数划分

当初一看到这一题的时候感觉像是搜索题,仔细一想才明白是一道区间dp题,既然是dp,当然要先找到状态了,设dp[i][j]为前i位中存在j个乘号
我们以a[i][j]表示第i位到第j位的值,则可以推出状态转移方程为dp[i][j] = max(dp[i][j], dp[i][k] * a[k+1][j]);
附上代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = + ; ll a[N][N], dp[N][N];
int n, T, c[N];
char s[N]; void work(){
for(int j = ; j < n; j ++){
for(int i = ; i <= strlen(s); i ++){
for(int k = ; k <= i; k ++){
if(j==)
dp[i][] = a[][i];
else
dp[i][j] = max(dp[i][j], dp[k][j-] * a[k+][i]);
/*for(int p = 1; p <= strlen(s); p ++){
for(int q = 0; q < n; q ++)
printf("%d ", dp[p][q]);
puts("");
}*/
}
}
}
printf("%lld\n", dp[strlen(s)][n-]);
} int main(){
scanf("%d", &T);
while(T--){
scanf("%s%d" , s, &n);
int flag = ;
if(n > strlen(s)){
printf("0\n");
continue;
}
memset(a, , sizeof(a));
memset(dp, , sizeof(dp));
for(int i = ; i < strlen(s); i ++)
c[i+] = s[i] - '';
for(int i = ; i <= strlen(s); i ++){
for(int j = i; j <= strlen(s); j ++){
a[i][j] = a[i][j-] * + c[i];
}
}
}
/*for(int i = 1; i <= strlen(s); i ++){
for(int j = i; j <= strlen(s); j ++)
printf("%I64d ", a[i][j]);
puts("");
}*/
work();
}
return ;
}
区间dp的典例的更多相关文章
- POJ - 3280Cheapest Palindrome-经典区间DP
POJ - 3280 Cheapest Palindrome Time Limit: 2000MS Memory Limit: 65536KB 64bit IO Format: %I64d & ...
- 以石子合并为例的区间DP
区间DP,是一类具有较为固定解法的DP,一般的思路都是: first.初始化区间长度为1的情况(一般区间长度为1的较易于初始化) second. for(枚举区间长度2~n){ for(枚举左端点){ ...
- 【BZOJ-1260】涂色paint 区间DP
1260: [CQOI2007]涂色paint Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 1147 Solved: 698[Submit][Sta ...
- light oj 1422 Halloween Costumes (区间dp)
题目链接:http://vjudge.net/contest/141291#problem/D 题意:有n个地方,每个地方要穿一种衣服,衣服可以嵌套穿,一旦脱下的衣服不能再穿,除非穿同样的一件新的,问 ...
- HDU 5115 Dire Wolf 区间dp
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5115 Dire Wolf Time Limit: 5000/5000 MS (Java/Others ...
- [kuangbin带你飞]专题二十二 区间DP
ID Origin Title 17 / 60 Problem A ZOJ 3537 Cake 54 / 105 Problem B LightOJ 1422 Hallowee ...
- HDU 5151 Sit sit sit 区间DP + 排列组合
Sit sit sit 问题描述 在一个XX大学中有NN张椅子排成一排,椅子上都没有人,每张椅子都有颜色,分别为蓝色或者红色. 接下来依次来了NN个学生,标号依次为1,2,3,...,N. 对于每个学 ...
- cdoj 1131 男神的礼物 区间dp
男神的礼物 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/1131 Descr ...
- 合并傻子//区间dp
P1062 合并傻子 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 从前有一堆傻子,钟某人要合并他们~但是,合并傻子是要掉RP的...... 描述 在一个园 ...
随机推荐
- android JSON解析之JSONObject与GSON
1.写在前面 JSON数据是android网络开发中常见的数据格式,JSON最常见的传输方法是使用HTTP协议,关于android开发中HTTP协议的使用方法可参考我的另一篇随笔android网络编程 ...
- Report List Controls
Report风格的ListCtrl的扩展,原文链接地址:http://www.codeproject.com/Articles/5560/Another-Report-List-Control 1.列 ...
- PL/SQL之--变量
一.PL/SQL 简介 PL/SQL也是一种程序语言,叫做过程化SQL语言(Procedural Language/SQL).PL/SQL是oracle对sql语句的一种扩展,在普通SQL语句的使用上 ...
- Tomcat报java.lang.ClassNotFoundException: 1catalina.org.apache.juli.FileHandler
最近在生产环境部署Tomcat的时候,在启动的时候,在控制台报"java.lang.ClassNotFoundException: 1catalina.org.apache.juli.Fil ...
- oracle错误(ORA-01691),单个数据文件大小限制问题
1.问题:数据库从其他库同步一张大表时,出现错误 ERROR at line : ORA-: illegal parameter value in OCI lob function ORA-: pre ...
- 在Windows2012下配置Mercurial
所需的安装文件: xampp-win32-1.8.3-4-VC11-installer.exe python-2.7.7.amd64.msi tortoisehg-3.0.1-x64.msi merc ...
- CocurrentHashMap和Hashtable的区别
集合类是Java API的核心,但是我觉得要用好它们是一种艺术.我总结了一些个人的经验,譬如使用ArrayList能够提高性能,而不再需要过时的Vector了,等等.JDK 1.5引入了一些好用的并发 ...
- Web性能优化之动态合并JS/CSS文件并缓存客户端
来源:微信公众号CodeL 在Web开发过程中,会产生很多的js/css文件,传统的引用外部文件的方式会产生多次的http请求,从而加重服务器负担且网页加载缓慢,如何在一次请求中将多个文件一次加载出来 ...
- 使用LVS实现负载平衡之Windows Server 2008配置
LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统.本项目在1998年5月由章文嵩博士成立,是中国国内最早出现的自由软件项目之一.承载于 II ...
- selenium获取html的表格单元格数据
获取网页的表格的某个单元格的值,思路: 1.获取表格 2.获取表格的所有行 3.根据某一行获取该行的所有列 4.根据某一列获得该行该列的单元格值 根据以上思路,可以知道,只需要行.列就可以得到单元格的 ...