51nod 1154 dp

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1154

1154 回文串划分

基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题

收藏

关注

有一个字符串S,求S最少可以被划分为多少个回文串。

例如:abbaabaa,有多种划分方式。

a|bb|aabaa - 3 个回文串

a|bb|a|aba|a - 5 个回文串

a|b|b|a|a|b|a|a - 8 个回文串

其中第1种划分方式的划分数量最少。

Input

输入字符串S(S的长度<= 5000)。

Output

输出最少的划分数量。

Input示例

abbaabaa

Output示例

3原本以为N^2会爆炸后来发现好像也不会= =倒是题意搞懵逼我了,题意是必须全部划分为回文子串,求最少划分几个,我以为可以出现非回文子串,就是0......天真dp[i]表示前i个字符的答案,第i个字符可能单独也可能与前面的某一串相连构成一个回文串,答案就是 dp[i]=MIN{dp[j]+1 | j<i&&j+1--i构成回文串}
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 #define inf 0x3f3f3f3f
 5 LL mod=1e9+7;
 6 int dp[5005];
 7 char s[5005];
 8 bool ok(int a,int b)
 9 {
10     int m=b-((b-a)>>1);
11     for(int i=a,j=b;i<=m;++i,--j)
12         if(s[i]!=s[j]) return 0;
13     return 1;
14 }
15 int main()
16 {
17     int N,i,j;
18     scanf("%s",s+1);
19     N=strlen(s+1);
20     for(i=1;i<=N;++i)
21     {
22         dp[i]=dp[i-1]+1;
23         for(j=0;j<i;++j)
24         {
25             if(ok(j+1,i)&&dp[i]>dp[j]+1) dp[i]=dp[j]+1;
26         }
27     }
28     printf("%d\n",dp[N]);
29     return 0;
30 }
时间: 2024-10-12 04:10:49

51nod 1154 dp的相关文章

51nod 1270 dp

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1270 简单的线性dp,最近狂刷水题真的是...药丸 差值最大得话要么是峰顶要么是最小的1,不可能处在中间状态,那样显然没有峰值的贡献大,想通这一点之后方程就好写了, dp[i][0]表示第i个数取最小值的最大代价,dp[i][1]相反. 有 dp[i][0]=max(dp[i-1][0],dp[i-1][1]+a[i-1]-1); dp[i][1]=max(dp[i-1

[51nod]A树的双直径

题目链接: 51nod 树形\(DP\)+换根\(DP\). 最直观的想法是枚举一条边断开,在两颗子树中求最大直径相乘然后取最大值. 不过这题可能出现负数,那么答案可能是正数\(\times\)正数或者负数\(\times\)负数. 其实只需要考虑正数的情况(负数把边全部取反即可) 那么设枚举边\((x,y)\),其中\(x\)为\(y\)的父亲 那么我们需要求出以\(y\)为根子树中的最长链和除去\(x\)子树外的最长链 对于\(y\)子树中的最长链\(InMax[y]\),我们可以先考虑求出

51nod 1201 整数划分(dp)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1201 题解:显然是一道dp,不妨设dp[i][j]表示数字i分成j个一共有几种分法. 那么转移方程式为: dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1] 表示将i - 1划分为j个数,然后j个数都+1 还是不重复,将i - 1划分为j - 1个数,然后j - 1个数都+1,再加上1这个数. 然后就是j的范围要知道1+2+

51nod 1406 位运算/dp

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1406 1406 与查询 题目来源: CodeForces 基准时间限制:2 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 收藏 关注 有n个整数.输出他之中和x相与之后结果为x的有多少个.x从0到1,000,000 Input 第一行输入一个整数n.(1<=n<=1,000,000). 第二行有n个整数a[0],a[1],a[2],...a[n-1

51nod 1412 AVL树的种类(经典dp)

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1412 题意: 思路: 经典dp!!!可惜我想不到!! $dp[i][k]$表示i个结点,最大深度为k的形态数. 它的转移方程就是: dp[i][k] += dp[i - 1 - j][k - 1] * dp[j][k - 1] dp[i][k] += 2 * dp[i - 1 - j][k - 2] * dp[j][k - 1] j是右子树结点个数,如果除去根结点,是不

51NOD 1202 子序列个数 DP

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1202&judgeId=225600 这题看起来挺复杂,但是真正的dp还是挺好理解的.唯独是想不到的,应该把样例模拟一遍. 比如1.2.4.2 考虑第一个,只有"1"这一个子序列 考虑前两个,有:"1", "12", "2" 前三个,有:"1", "12"

51nod 1043 幸运号码(数位dp)

题目链接:51nod 1043 幸运号码 题解:dp[i][j]表示 i 个数和为 j 的总数(包含0开头情况) dp[i][j] = dp[i-1][j-k] i & 1 :这里用滚动数组节省内存 非0开头的情况 * 0开头的情况:(dp[n&1][i]-dp[(n-1)&1][i]) *dp[n&1][i],最后将其累加即为结果. 1 #include<cstdio> 2 #include<algorithm> 3 #include<cst

51Nod 1083 矩阵取数问题(矩阵取数dp,基础题)

1083 矩阵取数问题 基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题 一个N*N矩阵中有不同的正整数,经过这个格子,就能获得相应价值的奖励,从左上走到右下,只能向下向右走,求能够获得的最大价值. 例如:3 * 3的方格. 1 3 3 2 1 3 2 2 1 能够获得的最大价值为:11. Input 第1行:N,N为矩阵的大小.(2 <= N <= 500) 第2 - N + 1行:每行N个数,中间用空格隔开,对应格子中奖励的价值.(1 <= N[i] 

51nod 1412 AVL树的种类(dp)

题目链接:51nod 1412 AVL树的种类 开始做的时候把深度开得过小了结果一直WA,是我天真了.. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 using namespace std; 6 typedef long long ll; 7 const int mod = 1e9+7; 8 const int N = 2001; 9 ll