1. 一维的动态规划
1) Triangle
每个单元到最底层的最短路径path[i][j]为path[i+1][j]和path[i+1][j+1]中的较小值。
2) Decode Ways
f[i]记录s[0]...s[i]可选择的解码方式数。
如果s[i]为0,那么必须与s[i-1]组合且s[i-1]必须为1或2,此时s[i] = s[i-2]。
如果s[i]不为0,那么这一位可以单独解码或和前一位一起解码,所以s[i]=s[i-1]+s[i-2]。
2. 两维的动态规划
1) Word Break:
f[i, j]表示子串s[i]...s[j]是否可以表示成若干单词组成的句子。
递推公式:如果存在i<=k<j,满足f[i,k]=true且f[k+1,j]=true,则f[i,j] = true。
初始条件:若f[i,j]就是个单词,则f[i,j]=true。
2) Palindrome Partition
f[i,j]表示子串s[i]...s[j]是否是回文。
递推公式:如果s[i]=s[j],则f[i,j] = f[i+1,j-1]。否则,f[i,j] = false。
初始条件:f[i,i] = true。
然后用回溯的方法,构造每个合法的分割。
for(i=begin;i<sLen;i++)
{
if(isPalindrome[begin][i])
{
string substr = s.substr(begin, i-begin+1);
temp.push_back(substr);
Build(s, i+1, isPalindrome, temp, result);
temp.pop_back();
}
}
3) Palindrome Partition II
在与Palindrome Partition相同的动态规划基础上,还要计算最小的分割是几次分割。
minCut[i]表示子串s[0]...s[i]的最小分割次数。
递推公式:如果存在0<=k<i,满足子串s[k+1]...s[i]是个回文,且minCut[k]+1小于当前的minCut[i],则更新minCut[i]。
初始条件:minCut[i] = i。
// find min cut
// minCut[i]: the min cut of string [0, 1, ..., i]
int *minCut;
minCut = new int[sLen];
for(i=0;i<sLen;i++)
{
// initialize
if(isPalindrome[0][i])
{
minCut[i] = 0;
continue;
}
minCut[i] = i;
// find k, making string [k+1, ..., i] palindrome, and get minCut[k]
for(k=0;k<i;k++)
{
if(isPalindrome[k+1][i] && minCut[k]+1<minCut[i])
minCut[i] = minCut[k] + 1;
}
}
4) Interleaving String
f[i][j]表示s1[i]和s2[j]是否能够拼出s3[i+j+1]。
如果s3[i+j+1]等于s1[i]也等于s2[j],那么f[i][j] = f[i-1][j] || f[i][j-1]。如果s2[i+j+1]只等于s1[i],那么f[i][j] = f[i-1][j]。如果s2[i+j+1]只等于s2[j],那么f[i][j] = f[i][j-1]。否则为false。