原题连接:
https://www.acwing.com/problem/content/description/55/
LeetCode连接:
https://leetcode.cn/problems/ba-shu-zi-fan-yi-cheng-zi-fu-chuan-lcof/
这是原本按照我的状态表示和状态转移写的代码:
class Solution {
public:
int getTranslationCount(string s) {
/*
计数类DP,是怎么想到用f[i]表示的呢??
f[i]表示前i个字母有多少种情况。
分为两种情况:
1. 只考虑s[i]
2. 考虑s[i - 1] 和 s[i], 但是此时这俩字母组成的二位数需要满足
10<= <=25
f[i]等于这两种情况相加。
处理边界情况:
f[0] = 1
答案:
f[n - 1]
*/
int n = s.size();
if(n == 1) return 1;
vector<int> f(n + 1);
// 先预处理好f[0]和f[1]
f[0] = 1;
f[1] = 1;
int t = (s[0] - '0') * 10 + s[1] - '0';
if(10 <= t && t <= 25) f[1] += 1;
for (int i = 2; i < n; i ++ ){
f[i] = f[i - 1];
int t = (s[i - 1] - '0') * 10 + s[i] - '0';
if(10 <= t && t <= 25) f[i] += f[i - 2];
}
return f[n - 1];
}
};
这是y总,处理过后的代码。为了防止i - 2越界,他直接加了一个偏移量,向右偏移了一位
f[i+1]表示前i个数的计数情况。这样就不用单独处理f[1]了。
class Solution {
public:
int getTranslationCount(string s) {
/*
f[1]和f[0]都是1,不过这样f[0]不好解释了,不容易理解。在这种情况下,为了更好地解释为啥f[0] = 1.
问题:为什么一个数字都没有的方案数是1?是凑出来的。
f[0]代表翻译前0个数字的方法数,这样的状态定义其实是没有实际意义的,但是f[0]的值 需要保证边界是对的,即f[1]和f[2]是对的。比如说,翻译前1个数只有一种方法,将其单独翻译, 即f[1] = f[1 - 1] = 1。翻译前两个数,
如果第1个数和第2个数可以组合起来翻译,那么f[2] = f[1] + f[0] = 2 ,否则只能单独翻译第2个数,即f[2] = f[1] = 1。因此,在任何情况下f[0]取1都可以保证f[1]和f[2]是正确的,所以f[0]应该取1
*/
int n = s.size();
vector<int> f(n + 1);
f[0] = 1;
for (int i = 1; i <= n; i ++ ){
f[i] = f[i - 1];
if(i > 1){
// 然后这里也是用的f[i - 2] 和 f[i - 1]
int t = (s[i - 2] - '0') * 10 + s[i - 1] - '0';
if(10 <= t && t <= 25) f[i] += f[i - 2];
}
}
// 所以最后返回的也是f[n]
return f[n];
}
};