区间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的典例的更多相关文章

  1. POJ - 3280Cheapest Palindrome-经典区间DP

    POJ - 3280 Cheapest Palindrome Time Limit: 2000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & ...

  2. 以石子合并为例的区间DP

    区间DP,是一类具有较为固定解法的DP,一般的思路都是: first.初始化区间长度为1的情况(一般区间长度为1的较易于初始化) second. for(枚举区间长度2~n){ for(枚举左端点){ ...

  3. 【BZOJ-1260】涂色paint 区间DP

    1260: [CQOI2007]涂色paint Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 1147  Solved: 698[Submit][Sta ...

  4. light oj 1422 Halloween Costumes (区间dp)

    题目链接:http://vjudge.net/contest/141291#problem/D 题意:有n个地方,每个地方要穿一种衣服,衣服可以嵌套穿,一旦脱下的衣服不能再穿,除非穿同样的一件新的,问 ...

  5. HDU 5115 Dire Wolf 区间dp

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5115 Dire Wolf Time Limit: 5000/5000 MS (Java/Others ...

  6. [kuangbin带你飞]专题二十二 区间DP

            ID Origin Title   17 / 60 Problem A ZOJ 3537 Cake   54 / 105 Problem B LightOJ 1422 Hallowee ...

  7. HDU 5151 Sit sit sit 区间DP + 排列组合

    Sit sit sit 问题描述 在一个XX大学中有NN张椅子排成一排,椅子上都没有人,每张椅子都有颜色,分别为蓝色或者红色. 接下来依次来了NN个学生,标号依次为1,2,3,...,N. 对于每个学 ...

  8. cdoj 1131 男神的礼物 区间dp

    男神的礼物 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/1131 Descr ...

  9. 合并傻子//区间dp

    P1062 合并傻子 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 从前有一堆傻子,钟某人要合并他们~但是,合并傻子是要掉RP的...... 描述 在一个园 ...

随机推荐

  1. CentOS下安装实时检测网络带宽的小工具bmon

    首先下载rpmforge-release扩展的rpm包 32位操作系统:wget http://www.sudu.us/Tools/bmon/rpmforge-release-0.3.6-1.el5. ...

  2. 记录Hibernate的缓存知识

    一.Hibernate缓存的作用 Hibernate是一个持久层框架,Hibernate要经常访问物理数据库.为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能,Hibernate的缓 ...

  3. 【CSharp】C#开发ActiveX插件

    这几天Web项目中需要用到ActiveX插件(PS:听说这个是好久好久的东西了...),由于项目中需要调用本地资源所以只能研究研究这位老兄了. 先说说自己学习他的经历,开始的时候是用百度引擎检索自己所 ...

  4. 剔除editor编辑器中的HTML标签

    1.剔除editor编辑器中的HTML标签 public static string striphtml(string strhtml)    {        string stroutput = ...

  5. Java递归实现操作系统文件的复制、粘贴和删除功能

    通过Java IO递归实现操作系统对文件的复制.粘贴和删除功能,剪切=复制+粘贴+删除 代码示例: import java.io.BufferedInputStream; import java.io ...

  6. 安装node.js+express for win7的Web开发环境配置

    1.安装 node.js. 进入官网的下载地址:http://www.nodejs.org/download/ . 选择Windows Installer或者选择Windows Installer ( ...

  7. PL/SQL之--函数

    一.函数 函数是作为数据库对象存储在oracle数据库中,函数又被称为PL/SQL子程序.oracle处理使用系统提供的函数之外,用户还可以自己定义函数.函数通常被作为一个表达式来调用或存储过程的一个 ...

  8. 从SqlServer现有数据生成Insert脚本

    步骤1,打开"Generate and Publish Objects"向导.右键点击要导出数据的数据库,选择Taks->GenerateScript 步骤2,选择要导出数据 ...

  9. 百度地图秘钥ak的获取

    今天打开网站的时候出现了这个问题“百度未授权使用地图API, 可能是因为您提供的密钥不是有效的百度开放平台密钥或此密钥未对本应用的百度地图JavasoriptAPI授权.....”经过研究终于知道什么 ...

  10. phpcms v9调用多个栏目下文章的方法

    示例:{pc:get sql="SELECT * from v9_news where status=99 and catid in(6,7,8) order by id DESC" ...