这题一开始没想到dp(动态规划),所以弄了好久好久。后来看别人的blog,知道是dp,就根据推导公式写,结果还是写错,后来发现原来是
自己少处理当前某个位置的数为0的情况。
思路:每次新加入一个数字处理时
(1)不为0
直接拼接的话,那么个数值时可能没变的,如21,原本是3,再加1,可能个数还是1,因为31大于26.
此时再考虑另一种情况,那就是跟前一位结合,如果结合后小于27,那么就是cnt = f1 + f2,因为不拼接是等于f2,现在多一个拼接成功,那么需要
增加f1的可能性的值
(2)为0
这个比较好说,直接等于前2个位置的值,因为0拼接没啥意义,如果可以跟前一位结合成功的话,还是算一个值,不会有11;1,1;这种情况
它就是10。所以就知道是等于前两个位置的。再之前的以此类推。
cnt:个数值,f1,f2:前两位和前一位位置的个数值,
总的分2种大情况
1 当前输入为0的话,个数值不变,cnt = f1
2 不为0的情况
a) 当前输入值与前一位值构成小于27的数大于10的数,大于10是必须的,因为前一位的值可能为0!则cnt=f1+f2
b)否则cnt = f2
然后更新f1和f2的值
#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
using namespace std;
int main()
{
// freopen("input.txt","r",stdin);
string s;
while (cin >> s && s != "0") {
long long f1, f2, cnt;
long long i, tmp, n;
n = s.size();
f1 = 1;
f2 = 1;
if (n >= 2 && s[1] != '0'&& (s[0] - '0')*10 + s[1]-'0' < 27)
f2++;
cnt = f2;
for (i = 2; i < n; ++i) {
if (s[i] != '0') {
tmp = (s[i-1] - '0')*10 + s[i]-'0';
if (tmp <= 26 && tmp > 10)
cnt = f1 + f2;
else
cnt = f2;
}
else
cnt = f1;
f1 = f2;
f2 = cnt;
}
printf("%d\n",cnt);
}
return 0;
}