区间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. Java线程池的实现

    线程池的作用: 一个线程的周期分为:创建.运行.销毁三个阶段. 处理一个任务时,首先创建一个任务线程,然后执行任务,完了还要销毁线程.而线程只有处于运行状态的时候,才是真的在处理我们交给它的任务,这个 ...

  2. 2013MPD上海6.23 PM 光耀:读心术,用户心理的产品之道

    创新的前提是:制度与组织的创新!!!!!!!!!!!!!! 光耀:腾讯互联网业务产品经理(腾讯公司互联网业务系统产品经理.在电子商务.社会化媒体等方面有深入研究.参与腾讯多个重要项目产品工作) 什么是 ...

  3. netty-socketio使用namespace

    一.简介 netty-socketio中的namespace可以用于区别在相同连接地址下的不同用户,当两个不同的用户打开同一个页面的时候,可以使用namespace用来标记不同用户.例如我们可以在用户 ...

  4. IIS7上设置MIME让其支持android和Iphone的更新下载

    Android APP的MIME: 文件扩展名:.apk MIME类型:application/vnd.android.package-archive iPhone APP的MIME: 文件扩展名:. ...

  5. html,js简单保存textarea换行格式

    有时候我们在做表单提交时,往往需要把html标签保存起来,但是textarea不保存换行的信息,所以我们需要用js来实现保存textarea的换行等HTM标签.真正让HTML文本框里的换换等格式保留下 ...

  6. Lua面向对象编程

    Lua中的table就是一种对象,看以下一段简单的代码: , b = } , b = } local tb3 = tb1 if tb1 == tb2 then print("tb1 == t ...

  7. Webshell实现与隐藏探究

    一.什么是webshell webshell简介 webshell,顾名思义:web指的是在web服务器上,而shell是用脚本语言编写的脚本程序,webshell就是就是web的一个管理 工具,可以 ...

  8. spark Basic code demo

    spark-shell --master=spark://namenode01:7077 --executor-memory 2g --driver-class-path /app/spark141/ ...

  9. ok,今天讲讲linux的部分指令吧

    Linux布置服务  cd 进入   ../      上一层目录    sh shutdown.sh   -------tomcat的关闭指令  sh startup.sh       ------ ...

  10. 【实践】jdbc批量插入数据

    参考文献:http://my.oschina.net/u/1452675/blog/203670 http://superjavason.iteye.com/blog/255423 /*测试批量写入数 ...