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

很明显的区间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. 学习6__STM32--SPI外设之中断收发---

    <目标> STM32双机 SPI中断收发通信 <描述> # STM32双机配置为一主一从模式 # 采用主机中断发送,从机中断接收 # 收发机制采用不间断收发(发送为空就发送,接 ...

  2. 将句子表示为向量(上):无监督句子表示学习(sentence embedding)

    1. 引言 word embedding技术如word2vec,glove等已经广泛应用于NLP,极大地推动了NLP的发展.既然词可以embedding,句子也应该可以(其实,万物皆可embeddin ...

  3. Windows的DOS命令基础

    Windows的DOS命令基础 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 1.dir: 查看当前路径下的目录(directory)详细信息 . 详细信息: a>.dir ...

  4. Spark记录-Scala数组

    Scala提供了一种数据结构叫作数组,数组是一种存储了相同类型元素的固定大小顺序集合.数组用于存储数据集合,但将数组视为相同类型变量的集合通常更为有用. 可以声明一个数组变量,例如:numbers,使 ...

  5. bzoj千题计划239:bzoj4069: [Apio2015]巴厘岛的雕塑

    http://www.lydsy.com/JudgeOnline/problem.php?id=4069 a!=1: 从高位到低位一位一位的算 记录下哪些位必须为0 dp[i][j] 表示前i个数分为 ...

  6. 官方资料&一些好的博客与技术点

    https://technet.microsoft.com/zh-cn/library/hh848794.aspxzh   https://msdn.microsoft.com/en-us/power ...

  7. JavaScript内部原理实践——真的懂JavaScript吗?(转)

    通过翻译了Dmitry A.Soshnikov的关于ECMAScript-262-3 JavaScript内部原理的文章, 从理论角度对JavaScript中部分特性的内部工作机制有了一定的了解. 但 ...

  8. 这两天自己模仿写的一个Asp.Net的显示分页方法 附加实体转换和存储过程

    之前自己一直用Aspnetpager控件来显示项目中的分页,但是每次都要拖一个aspnetpager的控件进去,感觉很不舒服,因为现在自己写的webform都不用服务器控件了,所以自己仿照aspnet ...

  9. 20155215 2016-2017-2 《Java程序设计》第8周学习总结

    20155215 2016-2017-2 <Java程序设计>第7周学习总结 教材学习内容总结 第十四章 NIO使用频道(Channel)来衔接数据节点.在处理数据时,NIO可以让你设置缓 ...

  10. django错误笔记——1242 Subquery returns more than 1 row

    在数据库查询操作过程中,子查询结果不唯一,导致外面的查询无法进行. 我的错误语句: rid = models.User.objects.filter(username=username).values ...