区间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的...... 描述 在一个园 ...
随机推荐
- jquery错误: Cannot read property ‘msie’ of undefined
背景 Web application, 引用了jquery 1.10.2和fancybox 1.3.4 现象 访问页面遭遇Cannot read property ‘msie’ of undefine ...
- MongoDB 存储引擎Wiredtiger原理剖析
今天开始看MongoDB 3.2的文档,发现了这么两句话 Support for Multiple Storage Engines MongoDB supports multiple storage ...
- Fragment学习笔记
Fragment为大量型号,尺寸,分辨率的设备提供了一种统一的UI优化方案.将Activity分解为多个Fragment,将极大地提高UI的灵活性,也更容易为一些新的设备配置带来更好的用户体验. on ...
- Android开发之 Android应用程序详细解析
我们继续的沿用上一篇所建立的应用. Android应用程序可以分为:应用程序源代码(.java),应用程序描述文件(.xml),各种资源. 可以这么理解: 安卓应用程序,通过java代码来实现其业务逻 ...
- CSS纯样式实现箭头、对话框等形状
在使用第三方框架bootstrap的时候,本以为其是图片实现的小箭头,后来使用开发工具查看是用CSS来实现的,现记录如下: 之前都没仔细去观注过其原理,都是拿来使用,在实现小箭头之前需要了解下CSS的 ...
- 学完STM32开发板,就选4412开发板让你有目标的学习嵌入式开发
600余页用户使用手册 linux实验手册(资料不断更新)100期配套零基础高清视频教程 轻松入门 (资料不断更新)2000人售后认证群 在线支持 售后无忧 源码全开源 原厂技术资料经典学习书籍推荐 ...
- selenium验证车贷计算器算法
1.验证页面上的车贷计算器算的结果是否与需求中给的公式结果一致. 页面图片: 代码如下(简单实现,需要优化): package com.test; import java.math.BigDecima ...
- ASP.NET URL伪静态重写实现方法
ASP.NET URL伪静态重写实现方法 首先说下,ASP.NET URL伪静态只是将~/a_1.html指向到了~/a.aspx?ID=1,但a.aspx还是真实存在的,你不用./a_1.html来 ...
- CSU 1116 Kingdoms
题意:给你n个城市,m条被摧毁的道路,每条道路修复需要c元,总共有k元,给你每个城市的人口,问在总费用不超过k的情况下 与1号城市相连的城市的最大总人口(包括1号城市) 思路:1号城市是必取的,剩余最 ...
- js对象深潜拷贝(从requirejs中抠出来的)
var op = Object.prototype, ostring = op.toString, hasOwn = op.hasOwnProperty; function isFunction(it ...