区间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. jquery错误: Cannot read property ‘msie’ of undefined

    背景 Web application, 引用了jquery 1.10.2和fancybox 1.3.4 现象 访问页面遭遇Cannot read property ‘msie’ of undefine ...

  2. MongoDB 存储引擎Wiredtiger原理剖析

    今天开始看MongoDB 3.2的文档,发现了这么两句话 Support for Multiple Storage Engines MongoDB supports multiple storage ...

  3. Fragment学习笔记

    Fragment为大量型号,尺寸,分辨率的设备提供了一种统一的UI优化方案.将Activity分解为多个Fragment,将极大地提高UI的灵活性,也更容易为一些新的设备配置带来更好的用户体验. on ...

  4. Android开发之 Android应用程序详细解析

    我们继续的沿用上一篇所建立的应用. Android应用程序可以分为:应用程序源代码(.java),应用程序描述文件(.xml),各种资源. 可以这么理解: 安卓应用程序,通过java代码来实现其业务逻 ...

  5. CSS纯样式实现箭头、对话框等形状

    在使用第三方框架bootstrap的时候,本以为其是图片实现的小箭头,后来使用开发工具查看是用CSS来实现的,现记录如下: 之前都没仔细去观注过其原理,都是拿来使用,在实现小箭头之前需要了解下CSS的 ...

  6. 学完STM32开发板,就选4412开发板让你有目标的学习嵌入式开发

    600余页用户使用手册 linux实验手册(资料不断更新)100期配套零基础高清视频教程 轻松入门 (资料不断更新)2000人售后认证群 在线支持 售后无忧 源码全开源  原厂技术资料经典学习书籍推荐 ...

  7. selenium验证车贷计算器算法

    1.验证页面上的车贷计算器算的结果是否与需求中给的公式结果一致. 页面图片: 代码如下(简单实现,需要优化): package com.test; import java.math.BigDecima ...

  8. ASP.NET URL伪静态重写实现方法

    ASP.NET URL伪静态重写实现方法 首先说下,ASP.NET URL伪静态只是将~/a_1.html指向到了~/a.aspx?ID=1,但a.aspx还是真实存在的,你不用./a_1.html来 ...

  9. CSU 1116 Kingdoms

    题意:给你n个城市,m条被摧毁的道路,每条道路修复需要c元,总共有k元,给你每个城市的人口,问在总费用不超过k的情况下 与1号城市相连的城市的最大总人口(包括1号城市) 思路:1号城市是必取的,剩余最 ...

  10. js对象深潜拷贝(从requirejs中抠出来的)

    var op = Object.prototype, ostring = op.toString, hasOwn = op.hasOwnProperty; function isFunction(it ...