题意:给定一个字符串 输出回文子序列的个数    一个字符也算一个回文

很明显的区间dp  就是要往区间小的压缩!

#include<bits/stdc++.h>
using namespace std;
//input
#define rep(i,x,y) for(int i=(x);i<=(y);++i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m);
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s)
#define LL long long
#define REP(i,N) for(int i=0;i<(N);i++)
#define CLR(A,v) memset(A,v,sizeof A)
//////////////////////////////////
#define N 1005
#define inf 0x3f3f3f3f
#define mod 10007
int dp[N][N]; int main()
{
int cas;
cin>>cas;
char s[];
int kase=;
while(cas--)
{
CLR(dp,);
RS(s+);
int n=strlen(s+);
rep(i,,n)
dp[i][i]=;//长度为一的区间肯定是一个回文 rep(i,,n)
for(int j=i-;j>=;j--)//这样保证了 len从小到大!
{
dp[j][i]=(dp[j+][i]+dp[j][i-]-dp[j+][i-]+mod)%mod;//容斥原理 反正就是要将dp往区间短的转移
if(s[i]==s[j])
dp[j][i] = (dp[j][i]+dp[j+][i-]++mod)%mod;//如果两边相等 那么这两个数可与i+1 到j-1里所有回文序列组成一个回文序列 且它们自己也是一个回文序列所以要加一
}
printf("Case %d: %d\n",++kase,dp[][n]);
}
}

Poj2955 括号匹配(一)

给出一个的只有'(',')','[',']'四种括号组成的字符串,求 最多 有多少个括号满足题目里所描述的完全匹配。

状态转移方程:dp[i][j]表示第i~j个字符间的最大匹配字符数。

if(s[i] 与 s[j]匹配) dp[i][j] = d[[i+1][j-1] +2;

dp[i][j] = max(dp[i][j],dp[i][k]+dp[k+1][j]);

#include<bits/stdc++.h>
using namespace std;
//input
#define rep(i,x,y) for(int i=(x);i<=(y);++i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m);
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s)
#define LL long long
#define REP(i,N) for(int i=0;i<(N);i++)
#define CLR(A,v) memset(A,v,sizeof A)
//////////////////////////////////
#define N 1005
#define inf 0x3f3f3f3f
#define mod 10007
int dp[N][N]; int main()
{
char s[N];
while(RS(s+)==)
{
CLR(dp,);
int n=strlen(s+);
rep(i,,n-)
// if(s[i]=='('&&s[i+1]==')'||s[i]=='['&&s[i+1]==']')
// dp[i][i+1]=1;
rep(len,,n)
for(int i=,j=i+len-;j<=n;i++,j=i+len-)
{
if((s[i]=='('&&s[j]==')')||(s[i]=='['&&s[j]==']'))
dp[i][j] = dp[i+][j-]+; //如果匹配,先更新 for(int k = i;k<j;k++)//区间合并
{//k<j
dp[i][j] = max(dp[i][j],dp[i][k]+dp[k+][j]);
}
}
cout<<dp[][n]<<endl;
}
}

整数划分

给出一个数n,要求在n的数位间插入(m-1)个乘号,将n分成了m段,求这m段的最大乘积。

样例输入

2

111 2

1111 2

样例输出

11

121

状态转移方程为

dp[i][j]=max(dp[i][j],dp[k][j-1]*num[k+1][i])

其中num[i][j]表示从s[i]到s[j]这段连续区间代表的数值。

#include<bits/stdc++.h>
using namespace std;
//input
#define rep(i,x,y) for(int i=(x);i<=(y);++i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m);
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s)
#define LL long long
#define REP(i,N) for(int i=0;i<(N);i++)
#define CLR(A,v) memset(A,v,sizeof A)
//////////////////////////////////
#define N 1005
#define inf 0x3f3f3f3f
#define mod 10007
int dp[N][N];
int num[ N][N];
int main()
{
char s[];
int n,m;
RS(s+);
RI(m);
n=strlen(s+);
rep(i,,n)
{
num[i][i]=s[i]-'';
rep(j,i+,n)
num[i][j]=num[i][j-]*+s[j]-'';
}
rep(i,,n)
dp[i][]=num[][i]; rep(j,,m-)//乘号一个个放入 因为每次dp[i][j] 由dp[i][j-1]转移而来 所以要j从小到大开始枚举 就像之前的要len从小到大开始枚举 因为每一个长区间取决于短区间
rep(i,j+,n)
rep(k,j,i-)
dp[i][j]=max(dp[i][j],dp[k][j-]*num[k+][i] );
cout<<dp[n][m-];
}

石子合并

题目描述

在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。

试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.

输入输出格式

输入格式:

数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.

输出格式:

输出共2行,第1行为最小得分,第2行为最大得分.

输入输出样例

输入样例#1: 复制

4
4 5 9 4
输出样例#1: 复制

43
54 特意去学习了区间dp 发现是区间dp入门题:石子划分的加强版 (当然 这题也是入门题) 对比那题 只是把链变成了环 可以得到区间dp的方程:
f[i][j] = max(f[i][k] + f[k+1][j] + 合并付出的代价) 这里的代价是 i到j的所有石子合 如果对dp顺序没有加以设计的话 很容易写出
i=1 to 10,j=1 to 10,k=1 to 9.当i=1,j=5,k=3时,显然状态f[k+1][j]没有结果。 f[4][5]的结果为i=4 j=5时求出的
所以区间dp对执行顺序是有考究的:
枚举j-i(也就是len),并在j-i中枚举k。这样,就能保证地推的正确
#include<bits/stdc++.h>
using namespace std;
//input
#define rep(i,x,y) for(int i=(x);i<=(y);++i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m);
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s)
#define LL long long
#define REP(i,N) for(int i=0;i<(N);i++)
#define CLR(A,v) memset(A,v,sizeof A)
//////////////////////////////////
#define N 300
#define inf 0x3f3f3f3f
int a[N];
int dp1[N][N];//max
int dp2[N][N];//min
int s[N];
int main()
{
int n;
RI(n);
rep(i,,n)
RI(a[i]),a[i+n]=a[i]; rep(i,,*n)
s[i]=s[i-]+a[i];
rep(len,,n-)
{
for(int i=,j=i+len;i<=*n&&j<=*n;i++,j=i+len )
{
dp2[i][j]=inf;//注意求最小值的初始化
for(int k=i;k<j;k++)
{
dp1[i][j]=max(dp1[i][j],dp1[i][k]+dp1[k+][j]+s[j]-s[i-] );
dp2[i][j]=min(dp2[i][j],dp2[i][k]+dp2[k+][j]+s[j]-s[i-] );
}
}
}
int ans1=;
int ans2=inf;
rep(i,,n)
{
ans1=max(ans1,dp1[i][i+n-]);//注意减一
ans2=min(ans2,dp2[i][i+n-]);
}
cout<<ans2<<endl<<ans1;
return ;
}

HDU4632 Poj2955 括号匹配 整数划分 P1880 [NOI1995]石子合并 区间DP总结的更多相关文章

  1. P1880 [NOI1995]石子合并[区间dp+四边形不等式优化]

    P1880 [NOI1995]石子合并 丢个地址就跑(关于四边形不等式复杂度是n方的证明) 嗯所以这题利用决策的单调性来减少k断点的枚举次数.具体看lyd书.这部分很生疏,但是我还是选择先不管了. # ...

  2. P1880 [NOI1995]石子合并 区间dp

    P1880 [NOI1995]石子合并 #include <bits/stdc++.h> using namespace std; ; const int inf = 0x3f3f3f3f ...

  3. P1880 [NOI1995]石子合并 区间dp+拆环成链

    思路 :一道经典的区间dp  唯一不同的时候 终点和起点相连  所以要拆环成链  只需要把1-n的数组在n+1-2*n复制一遍就行了 #include<bits/stdc++.h> usi ...

  4. 洛谷 P1880 [NOI1995] 石子合并(区间DP)

    传送门 https://www.cnblogs.com/violet-acmer/p/9852294.html 题解: 这道题是石子合并问题稍微升级版 这道题和经典石子合并问题的不同在于,经典的石子合 ...

  5. P1880 [NOI1995]石子合并[环形DP]

    题目来源:洛谷 题目描述 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1个算法,计算出将 ...

  6. 区间DP小结 及例题分析:P1880 [NOI1995]石子合并,P1063 能量项链

    区间类动态规划 一.基本概念 区间类动态规划是线性动态规划的拓展,它在分阶段划分问题时,与阶段中元素出现的顺序和由前一阶段的那些元素合并而来由很大的关系.例如状态f [ i ][ j ],它表示以已合 ...

  7. 洛谷 P1880 [NOI1995]石子合并 题解

    P1880 [NOI1995]石子合并 题目描述 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试 ...

  8. 【区间dp】- P1880 [NOI1995] 石子合并

    记录一下第一道ac的区间dp 题目:P1880 [NOI1995] 石子合并 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 代码: #include <iostream> ...

  9. 洛谷P1880 [NOI1995]石子合并 纪中21日c组T4 2119. 【2016-12-30普及组模拟】环状石子归并

    洛谷P1880 石子合并 纪中2119. 环状石子归并 洛谷传送门 题目描述1 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石 ...

随机推荐

  1. Meshgrid函数的基本用法(转载)

    在Numpy的官方文章里,meshgrid函数的英文描述也显得文绉绉的,理解起来有些难度. 可以这么理解,meshgrid函数用两个坐标轴上的点在平面上画网格. 用法: [X,Y]=meshgrid( ...

  2. 「Vue」JS方法学习

    1.构造函数 大写开头的,能被NEW一个新实例,实例即执行回调函数 异步返回数据.then指定回调函数的时候,成功的回调函数必须传,失败的回调可以不传 var fs = require('fs') f ...

  3. OpenStack 镜像服务 Glance部署(六)

    Glance介绍 创建虚拟机我们需要有glance的支持,因为glance是提供镜像的服务. Glance有两个比较重要的服务: Glance-api:接受云系统镜像的构建.删除.读取请求 Glanc ...

  4. hdu 5079 Square

    http://acm.hdu.edu.cn/showproblem.php?pid=5079 题意: n*n网格,每个格子可以涂黑色或白色,有的格子必须涂黑色 问最大白色正方形边长分别为0,1,2,… ...

  5. scala 基础知识总结

    在最开始处引入 log 相关的 包 import org.apache.log4j.{Logger,Level} 在需要屏蔽日志输出的地方加上这两行代码 // 屏蔽不必要的日志显示在终端上 Logge ...

  6. Spring Mvc 一个接口多个继承; (八)

    在 spring 注解实现里,一个接口一般是不能多继承的! 除非在 bean 配置文件里有 针对这个 实现类的配置: <beans:bean id="icService" c ...

  7. 20155306 2016-2017-2 《Java程序设计》第5周学习总结

    20155306 2016-2017-2 <Java程序设计>第5周学习总结 教材学习内容总结 第八章 异常处理 8.1 语法与继承架构 Java中所有错误都会被打包为对象,运用try.c ...

  8. Docker学习笔记三 Dockerfile 指令 定制镜像

    本文地址:https://www.cnblogs.com/veinyin/p/10412079.html  镜像是分层存储的,每一层都是独立存在的,修改当前层并不会修改其依赖的上一层,删除某一层也只是 ...

  9. C# IEqualityComparer类型参数写法

    最近在使用Union.Except时,由于默认的对比不太好使,所以需要自定义对比器,下面附上代码. class MaterialListComparer : IEqualityComparer< ...

  10. 【ARTS】01_04_左耳听风-20181203~1209

    ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 Algo ...