csu 1510 Happy Robot(字符串DP,记忆化搜索)
2016-08-16 10:31
253 查看
Happy RobotTime Limit: 1 Sec Memory Limit:
128 MB
Submit: 182 Solved: 85
[Submit][Status][Web
Board]
题意:给一个字符串,包含有四种字符,F表示向前走,L表示在当前位置向左转,R表示在当前位置向右转,?表示执行上面三种任意一种都可以
机器人从(0,0)开始,输出x,y的最小值和最大值
思路:用记忆化搜索从后往前搜索,搜过的位置可以直接返回。DP里要保存在当前这个位置朝向某个方向极值
队友还提供了一种字符串DP的思路,其实也差不多。
关键在于此题不能在二维平面考虑,要在字符串上考虑才可以。
这里给出两个代码,记忆化搜索的方向是上下左右,字符串DP的方向是上右下左
代码1:
代码2:
#include<iostream>
#include<cstdio>
#include<cstring>
#define max(a,b) (a) > (b) ? (a) : (b)
#define min(a,b) (a) < (b) ? (a) : (b)
using namespace std;
const int maxn = 1005;
const int inf = 0x3f3f3f3f;
int dp[maxn][4],n;
char str[maxn];
int MAX(int a,int b,int c,int d)
{
return max(a,max(b,max(c,d)));
}
int MIN(int a,int b,int c,int d)
{
return min(a,min(b,min(c,d)));
}
void DP1()
{
for(int i = 0; i < n; i++)
for(int j = 0; j < 4; j++)
dp[i][j] = inf;
if(str[0] == 'F')
dp[0][1] = 1;
else if(str[0] == 'L')
dp[0][0] = 0;
else if(str[0] == 'R')
dp[0][2] = 0;
else
{
dp[0][0] = 0;
dp[0][1] = 1;
dp[0][2] = 0;
}
for(int i = 1; i < n; i++)
for(int j = 0; j < 4; j++) //上一个指令执行后的方向
{
if(str[i] == 'F') //前进
{
if(j == 0) //向上
dp[i][j] = min(dp[i][j],dp[i-1][j]);
else if(j == 1) //向右
dp[i][j] = min(dp[i][j],dp[i-1][j] + 1);
else if(j == 2) //向下
dp[i][j] = min(dp[i][j],dp[i-1][j]);
else //向左
dp[i][j] = min(dp[i][j],dp[i-1][j] - 1);
}
else if(str[i] == 'L')
{
int d = ((j - 1) % 4 + 4) % 4;
dp[i][d] = min(dp[i][d],dp[i-1][j]);
}
else if(str[i] == 'R')
{
int d = (j + 1) % 4;
dp[i][d] = min(dp[i][d],dp[i-1][j]);
}
else
{
if(j == 0) //向上
dp[i][j] = min(dp[i][j],dp[i-1][j]);
else if(j == 1) //向右
dp[i][j] = min(dp[i][j],dp[i-1][j] + 1);
else if(j == 2) //向下
dp[i][j] = min(dp[i][j],dp[i-1][j]);
else //向左
dp[i][j] = min(dp[i][j],dp[i-1][j] - 1);
int d = ((j - 1) % 4 + 4) % 4;
dp[i][d] = min(dp[i][d],dp[i-1][j]);
d = (j + 1) % 4;
dp[i][d] = min(dp[i][d],dp[i-1][j]);
}
}
}
void DP2()
{
for(int i = 0; i < n; i++)
for(int j = 0; j < 4; j++)
dp[i][j] = -inf;
if(str[0] == 'F')
dp[0][1] = 1;
else if(str[0] == 'L')
dp[0][0] = 0;
else if(str[0] == 'R')
dp[0][2] = 0;
else
{
dp[0][0] = 0;
dp[0][1] = 1;
dp[0][2] = 0;
}
for(int i = 1; i < n; i++)
for(int j = 0; j < 4; j++) //上一个指令执行后的方向
{
if(str[i] == 'F') //前进
{
if(j == 0) //向上
dp[i][j] = max(dp[i][j],dp[i-1][j]);
else if(j == 1) //向右
dp[i][j] = max(dp[i][j],dp[i-1][j] + 1);
else if(j == 2) //向下
dp[i][j] = max(dp[i][j],dp[i-1][j]);
else //向左
dp[i][j] = max(dp[i][j],dp[i-1][j] - 1);
}
else if(str[i] == 'L')
{
int d = ((j - 1) % 4 + 4) % 4;
dp[i][d] = max(dp[i][d],dp[i-1][j]);
}
else if(str[i] == 'R')
{
int d = (j + 1) % 4;
dp[i][d] = max(dp[i][d],dp[i-1][j]);
}
else
{
if(j == 0) //向上
dp[i][j] = max(dp[i][j],dp[i-1][j]);
else if(j == 1) //向右
dp[i][j] = max(dp[i][j],dp[i-1][j] + 1);
else if(j == 2) //向下
dp[i][j] = max(dp[i][j],dp[i-1][j]);
else //向左
dp[i][j] = max(dp[i][j],dp[i-1][j] - 1);
int d = ((j - 1) % 4 + 4) % 4;
dp[i][d] = max(dp[i][d],dp[i-1][j]);
d = (j + 1) % 4;
dp[i][d] = max(dp[i][d],dp[i-1][j]);
}
}
}
void DP3()
{
for(int i = 0; i < n; i++)
for(int j = 0; j < 4; j++)
dp[i][j] = inf;
if(str[0] == 'F')
dp[0][1] = 0;
else if(str[0] == 'L')
dp[0][0] = 0;
else if(str[0] == 'R')
dp[0][2] = 0;
else
{
dp[0][0] = 0;
dp[0][1] = 0;
dp[0][2] = 0;
}
for(int i = 1; i < n; i++)
for(int j = 0; j < 4; j++) //上一个指令执行后的方向
{
if(str[i] == 'F') //前进
{
if(j == 0) //向上
dp[i][j] = min(dp[i][j],dp[i-1][j] + 1);
else if(j == 1) //向右
dp[i][j] = min(dp[i][j],dp[i-1][j]);
else if(j == 2) //向下
dp[i][j] = min(dp[i][j],dp[i-1][j] - 1);
else //向左
dp[i][j] = min(dp[i][j],dp[i-1][j]);
}
else if(str[i] == 'L')
{
int d = ((j - 1) % 4 + 4) % 4;
dp[i][d] = min(dp[i][d],dp[i-1][j]);
}
else if(str[i] == 'R')
{
int d = (j + 1) % 4;
dp[i][d] = min(dp[i][d],dp[i-1][j]);
}
else
{
if(j == 0) //向上
dp[i][j] = min(dp[i][j],dp[i-1][j] + 1);
else if(j == 1) //向右
dp[i][j] = min(dp[i][j],dp[i-1][j]);
else if(j == 2) //向下
dp[i][j] = min(dp[i][j],dp[i-1][j] - 1);
else //向左
dp[i][j] = min(dp[i][j],dp[i-1][j]);
int d = ((j - 1) % 4 + 4) % 4;
dp[i][d] = min(dp[i][d],dp[i-1][j]);
d = (j + 1) % 4;
dp[i][d] = min(dp[i][d],dp[i-1][j]);
}
}
}
void DP4()
{
for(int i = 0; i < n; i++)
for(int j = 0; j < 4; j++)
dp[i][j] = -inf;
if(str[0] == 'F')
dp[0][1] = 0;
else if(str[0] == 'L')
dp[0][0] = 0;
else if(str[0] == 'R')
dp[0][2] = 0;
else
{
dp[0][0] = 0;
dp[0][1] = 0;
dp[0][2] = 0;
}
for(int i = 1; i < n; i++)
for(int j = 0; j < 4; j++) //上一个指令执行后的方向
{
if(str[i] == 'F') //前进
{
if(j == 0) //向上
dp[i][j] = max(dp[i][j],dp[i-1][j] + 1);
else if(j == 1) //向右
dp[i][j] = max(dp[i][j],dp[i-1][j]);
else if(j == 2) //向下
dp[i][j] = max(dp[i][j],dp[i-1][j] - 1);
else //向左
dp[i][j] = max(dp[i][j],dp[i-1][j]);
}
else if(str[i] == 'L')
{
int d = ((j - 1) % 4 + 4) % 4;
dp[i][d] = max(dp[i][d],dp[i-1][j]);
}
else if(str[i] == 'R')
{
int d = (j + 1) % 4;
dp[i][d] = max(dp[i][d],dp[i-1][j]);
}
else
{
if(j == 0) //向上
dp[i][j] = max(dp[i][j],dp[i-1][j] + 1);
else if(j == 1) //向右
dp[i][j] = max(dp[i][j],dp[i-1][j]);
else if(j == 2) //向下
dp[i][j] = max(dp[i][j],dp[i-1][j] - 1);
else //向左
dp[i][j] = max(dp[i][j],dp[i-1][j]);
int d = ((j - 1) % 4 + 4) % 4;
dp[i][d] = max(dp[i][d],dp[i-1][j]);
d = (j + 1) % 4;
dp[i][d] = max(dp[i][d],dp[i-1][j]);
}
}
}
int main()
{
int cas = 1;
while(scanf("%s",str)!=EOF)
{
n = strlen(str);
DP1();
printf("Case %d: %d ",cas++,MIN(dp[n-1][0],dp[n-1][1],dp[n-1][2],dp[n-1][3]));
DP2();
printf("%d ",MAX(dp[n-1][0],dp[n-1][1],dp[n-1][2],dp[n-1][3]));
DP3();
printf("%d ",MIN(dp[n-1][0],dp[n-1][1],dp[n-1][2],dp[n-1][3]));
DP4();
printf("%d\n",MAX(dp[n-1][0],dp[n-1][1],dp[n-1][2],dp[n-1][3]));
}
return 0;
}
128 MB
Submit: 182 Solved: 85
[Submit][Status][Web
Board]
Description
Input
There will be at most 1000 test cases. Each case contains a command sequence with no more than 1000 characters.Output
For each test case, print the case number, followed by minimal/maximal possible x (in this order), then the minimal/maximal possible y.Sample Input
F?F L?? LFFFRF
Sample Output
Case 1: 1 3 -1 1 Case 2: -1 1 0 2 Case 3: 1 1 3 3
题意:给一个字符串,包含有四种字符,F表示向前走,L表示在当前位置向左转,R表示在当前位置向右转,?表示执行上面三种任意一种都可以
机器人从(0,0)开始,输出x,y的最小值和最大值
思路:用记忆化搜索从后往前搜索,搜过的位置可以直接返回。DP里要保存在当前这个位置朝向某个方向极值
队友还提供了一种字符串DP的思路,其实也差不多。
关键在于此题不能在二维平面考虑,要在字符串上考虑才可以。
这里给出两个代码,记忆化搜索的方向是上下左右,字符串DP的方向是上右下左
代码1:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> using namespace std; #define N 1050 #define INF 99999999 struct Node { int minx,maxx,miny,maxy; } dp [4]; char a ; int vis [4]; int len; int Min(int b,int c,int d) { if(b>c) b=c; return b<d?b:d; } int Max(int b,int c,int d) { if(b<c) b=c; return b>d?b:d; } Node dfs(int k,int f) { if(vis[k][f]) return dp[k][f]; vis[k][f]=1; dp[k][f].minx=dp[k][f].maxx=dp[k][f].miny=dp[k][f].maxy=0; if(k==len-1) { if(a[k]=='F') { if(f==0) dp[k][f].maxy=1,dp[k][f].miny=1; else if(f==1) dp[k][f].maxy=-1,dp[k][f].miny=-1; else if(f==2) dp[k][f].minx=-1,dp[k][f].maxx=-1; else dp[k][f].minx=1,dp[k][f].maxx=1; } else if(a[k]=='?') { if(f==0) dp[k][f].maxy=1; else if(f==1) dp[k][f].miny=-1; else if(f==2) dp[k][f].minx=-1; else dp[k][f].maxx=1; } } else { if(a[k]=='L') { if(f==0) dp[k][f]=dfs(k+1,2); else if(f==1) dp[k][f]=dfs(k+1,3); else if(f==2) dp[k][f]=dfs(k+1,1); else dp[k][f]=dfs(k+1,0); } else if(a[k]=='R') { if(f==0) dp[k][f]=dfs(k+1,3); else if(f==1) dp[k][f]=dfs(k+1,2); else if(f==2) dp[k][f]=dfs(k+1,0); else dp[k][f]=dfs(k+1,1); } else if(a[k]=='F') { if(f==0) { dp[k][f]=dfs(k+1,0); dp[k][f].maxy++; dp[k][f].miny++; } else if(f==1) { dp[k][f]=dfs(k+1,1); dp[k][f].miny--; dp[k][f].maxy--; } else if(f==2) { dp[k][f]=dfs(k+1,2); dp[k][f].minx--; dp[k][f].maxx--; } else { dp[k][f]=dfs(k+1,3); dp[k][f].maxx++; dp[k][f].minx++; } } else { Node b,c,d,e; if(f==0) { b=dfs(k+1,0); b.maxy++; b.miny++; c=dfs(k+1,2); d=dfs(k+1,3); dp[k][f].minx=Min(b.minx,c.minx,d.minx); dp[k][f].maxx=Max(b.maxx,c.maxx,d.maxx); dp[k][f].miny=Min(b.miny,c.miny,d.miny); dp[k][f].maxy=Max(b.maxy,c.maxy,d.maxy); } else if(f==1) { b=dfs(k+1,1); b.maxy--; b.miny--; c=dfs(k+1,3); d=dfs(k+1,2); dp[k][f].minx=Min(b.minx,c.minx,d.minx); dp[k][f].maxx=Max(b.maxx,c.maxx,d.maxx); dp[k][f].miny=Min(b.miny,c.miny,d.miny); dp[k][f].maxy=Max(b.maxy,c.maxy,d.maxy); } else if(f==2) { b=dfs(k+1,2); b.maxx--; b.minx--; c=dfs(k+1,1); d=dfs(k+1,0); dp[k][f].minx=Min(b.minx,c.minx,d.minx); dp[k][f].maxx=Max(b.maxx,c.maxx,d.maxx); dp[k][f].miny=Min(b.miny,c.miny,d.miny); dp[k][f].maxy=Max(b.maxy,c.maxy,d.maxy); } else { b=dfs(k+1,3); b.maxx++; b.minx++; c=dfs(k+1,0); d=dfs(k+1,1); dp[k][f].minx=Min(b.minx,c.minx,d.minx); dp[k][f].maxx=Max(b.maxx,c.maxx,d.maxx); dp[k][f].miny=Min(b.miny,c.miny,d.miny); dp[k][f].maxy=Max(b.maxy,c.maxy,d.maxy); } } } return dp[k][f]; } int main() { int cas=1; while(~scanf("%s",a)) { len=strlen(a); memset(vis,0,sizeof(vis)); Node ans=dfs(0,3); printf("Case %d: %d %d %d %d\n",cas++,ans.minx,ans.maxx,ans.miny,ans.maxy); } return 0; }
代码2:
#include<iostream>
#include<cstdio>
#include<cstring>
#define max(a,b) (a) > (b) ? (a) : (b)
#define min(a,b) (a) < (b) ? (a) : (b)
using namespace std;
const int maxn = 1005;
const int inf = 0x3f3f3f3f;
int dp[maxn][4],n;
char str[maxn];
int MAX(int a,int b,int c,int d)
{
return max(a,max(b,max(c,d)));
}
int MIN(int a,int b,int c,int d)
{
return min(a,min(b,min(c,d)));
}
void DP1()
{
for(int i = 0; i < n; i++)
for(int j = 0; j < 4; j++)
dp[i][j] = inf;
if(str[0] == 'F')
dp[0][1] = 1;
else if(str[0] == 'L')
dp[0][0] = 0;
else if(str[0] == 'R')
dp[0][2] = 0;
else
{
dp[0][0] = 0;
dp[0][1] = 1;
dp[0][2] = 0;
}
for(int i = 1; i < n; i++)
for(int j = 0; j < 4; j++) //上一个指令执行后的方向
{
if(str[i] == 'F') //前进
{
if(j == 0) //向上
dp[i][j] = min(dp[i][j],dp[i-1][j]);
else if(j == 1) //向右
dp[i][j] = min(dp[i][j],dp[i-1][j] + 1);
else if(j == 2) //向下
dp[i][j] = min(dp[i][j],dp[i-1][j]);
else //向左
dp[i][j] = min(dp[i][j],dp[i-1][j] - 1);
}
else if(str[i] == 'L')
{
int d = ((j - 1) % 4 + 4) % 4;
dp[i][d] = min(dp[i][d],dp[i-1][j]);
}
else if(str[i] == 'R')
{
int d = (j + 1) % 4;
dp[i][d] = min(dp[i][d],dp[i-1][j]);
}
else
{
if(j == 0) //向上
dp[i][j] = min(dp[i][j],dp[i-1][j]);
else if(j == 1) //向右
dp[i][j] = min(dp[i][j],dp[i-1][j] + 1);
else if(j == 2) //向下
dp[i][j] = min(dp[i][j],dp[i-1][j]);
else //向左
dp[i][j] = min(dp[i][j],dp[i-1][j] - 1);
int d = ((j - 1) % 4 + 4) % 4;
dp[i][d] = min(dp[i][d],dp[i-1][j]);
d = (j + 1) % 4;
dp[i][d] = min(dp[i][d],dp[i-1][j]);
}
}
}
void DP2()
{
for(int i = 0; i < n; i++)
for(int j = 0; j < 4; j++)
dp[i][j] = -inf;
if(str[0] == 'F')
dp[0][1] = 1;
else if(str[0] == 'L')
dp[0][0] = 0;
else if(str[0] == 'R')
dp[0][2] = 0;
else
{
dp[0][0] = 0;
dp[0][1] = 1;
dp[0][2] = 0;
}
for(int i = 1; i < n; i++)
for(int j = 0; j < 4; j++) //上一个指令执行后的方向
{
if(str[i] == 'F') //前进
{
if(j == 0) //向上
dp[i][j] = max(dp[i][j],dp[i-1][j]);
else if(j == 1) //向右
dp[i][j] = max(dp[i][j],dp[i-1][j] + 1);
else if(j == 2) //向下
dp[i][j] = max(dp[i][j],dp[i-1][j]);
else //向左
dp[i][j] = max(dp[i][j],dp[i-1][j] - 1);
}
else if(str[i] == 'L')
{
int d = ((j - 1) % 4 + 4) % 4;
dp[i][d] = max(dp[i][d],dp[i-1][j]);
}
else if(str[i] == 'R')
{
int d = (j + 1) % 4;
dp[i][d] = max(dp[i][d],dp[i-1][j]);
}
else
{
if(j == 0) //向上
dp[i][j] = max(dp[i][j],dp[i-1][j]);
else if(j == 1) //向右
dp[i][j] = max(dp[i][j],dp[i-1][j] + 1);
else if(j == 2) //向下
dp[i][j] = max(dp[i][j],dp[i-1][j]);
else //向左
dp[i][j] = max(dp[i][j],dp[i-1][j] - 1);
int d = ((j - 1) % 4 + 4) % 4;
dp[i][d] = max(dp[i][d],dp[i-1][j]);
d = (j + 1) % 4;
dp[i][d] = max(dp[i][d],dp[i-1][j]);
}
}
}
void DP3()
{
for(int i = 0; i < n; i++)
for(int j = 0; j < 4; j++)
dp[i][j] = inf;
if(str[0] == 'F')
dp[0][1] = 0;
else if(str[0] == 'L')
dp[0][0] = 0;
else if(str[0] == 'R')
dp[0][2] = 0;
else
{
dp[0][0] = 0;
dp[0][1] = 0;
dp[0][2] = 0;
}
for(int i = 1; i < n; i++)
for(int j = 0; j < 4; j++) //上一个指令执行后的方向
{
if(str[i] == 'F') //前进
{
if(j == 0) //向上
dp[i][j] = min(dp[i][j],dp[i-1][j] + 1);
else if(j == 1) //向右
dp[i][j] = min(dp[i][j],dp[i-1][j]);
else if(j == 2) //向下
dp[i][j] = min(dp[i][j],dp[i-1][j] - 1);
else //向左
dp[i][j] = min(dp[i][j],dp[i-1][j]);
}
else if(str[i] == 'L')
{
int d = ((j - 1) % 4 + 4) % 4;
dp[i][d] = min(dp[i][d],dp[i-1][j]);
}
else if(str[i] == 'R')
{
int d = (j + 1) % 4;
dp[i][d] = min(dp[i][d],dp[i-1][j]);
}
else
{
if(j == 0) //向上
dp[i][j] = min(dp[i][j],dp[i-1][j] + 1);
else if(j == 1) //向右
dp[i][j] = min(dp[i][j],dp[i-1][j]);
else if(j == 2) //向下
dp[i][j] = min(dp[i][j],dp[i-1][j] - 1);
else //向左
dp[i][j] = min(dp[i][j],dp[i-1][j]);
int d = ((j - 1) % 4 + 4) % 4;
dp[i][d] = min(dp[i][d],dp[i-1][j]);
d = (j + 1) % 4;
dp[i][d] = min(dp[i][d],dp[i-1][j]);
}
}
}
void DP4()
{
for(int i = 0; i < n; i++)
for(int j = 0; j < 4; j++)
dp[i][j] = -inf;
if(str[0] == 'F')
dp[0][1] = 0;
else if(str[0] == 'L')
dp[0][0] = 0;
else if(str[0] == 'R')
dp[0][2] = 0;
else
{
dp[0][0] = 0;
dp[0][1] = 0;
dp[0][2] = 0;
}
for(int i = 1; i < n; i++)
for(int j = 0; j < 4; j++) //上一个指令执行后的方向
{
if(str[i] == 'F') //前进
{
if(j == 0) //向上
dp[i][j] = max(dp[i][j],dp[i-1][j] + 1);
else if(j == 1) //向右
dp[i][j] = max(dp[i][j],dp[i-1][j]);
else if(j == 2) //向下
dp[i][j] = max(dp[i][j],dp[i-1][j] - 1);
else //向左
dp[i][j] = max(dp[i][j],dp[i-1][j]);
}
else if(str[i] == 'L')
{
int d = ((j - 1) % 4 + 4) % 4;
dp[i][d] = max(dp[i][d],dp[i-1][j]);
}
else if(str[i] == 'R')
{
int d = (j + 1) % 4;
dp[i][d] = max(dp[i][d],dp[i-1][j]);
}
else
{
if(j == 0) //向上
dp[i][j] = max(dp[i][j],dp[i-1][j] + 1);
else if(j == 1) //向右
dp[i][j] = max(dp[i][j],dp[i-1][j]);
else if(j == 2) //向下
dp[i][j] = max(dp[i][j],dp[i-1][j] - 1);
else //向左
dp[i][j] = max(dp[i][j],dp[i-1][j]);
int d = ((j - 1) % 4 + 4) % 4;
dp[i][d] = max(dp[i][d],dp[i-1][j]);
d = (j + 1) % 4;
dp[i][d] = max(dp[i][d],dp[i-1][j]);
}
}
}
int main()
{
int cas = 1;
while(scanf("%s",str)!=EOF)
{
n = strlen(str);
DP1();
printf("Case %d: %d ",cas++,MIN(dp[n-1][0],dp[n-1][1],dp[n-1][2],dp[n-1][3]));
DP2();
printf("%d ",MAX(dp[n-1][0],dp[n-1][1],dp[n-1][2],dp[n-1][3]));
DP3();
printf("%d ",MIN(dp[n-1][0],dp[n-1][1],dp[n-1][2],dp[n-1][3]));
DP4();
printf("%d\n",MAX(dp[n-1][0],dp[n-1][1],dp[n-1][2],dp[n-1][3]));
}
return 0;
}
相关文章推荐
- CSU 1510 Happy Robot(字符串上的dp)
- CSU 1510 Happy Robot(字符串上的dp)
- 【bzoj1055】【区间DP 记忆化搜索】[HAOI2008]玩具取名 把所给的字符串缩成WING这四个字符之一
- CSU 1510 Happy Robot DP
- CSU 1510 Happy Robot
- CSU 1510Happy Robot(dp)
- Vijos P1118 统计单词个数(动态规划,划分型DP,字符串)
- hdu 4283 You Are the One(记忆化搜索,区间dp)
- 72:Edit Distance【DP】【字符串】
- poj3267--The Cow Lexicon(dp:字符串组合)
- uva10739(DP 回文字符串)
- HDU3427 Clickomania【记忆化搜索】【区间DP】
- 字符串DP——HDU 6017 Girls Love 233
- SDUT 2893-B(DP || 记忆化搜索)
- CSU-1835 Pry Sequence Transformation(DP)
- POJ_1088_(dp)(记忆化搜索)
- DP 回文字符串 南洋理工
- poj 1191棋盘分割(递归dp, 记忆化搜索)
- Codeforces Beta Round #17 C. Balance (字符串计数 dp)
- UVA - 11584 划分字符串的回文串子串; 简单dp