POJ 2033|SPOJ ACODE|Alphacode|动态规划

SPOJ:http://www.spoj.com/problems/ACODE/

题目翻译

A和B希望给对方发送聊天信息并且加密数据传输,他们讨论后希望这样加密数据:
A:“让我们用一种十分简单的加密方式:令字符’A’的编码为1,’B’的编码为2,以此类推,直到’Z’的编码是26。”
B:“mdzz,假设我发给你单词’BEAN’,加密后为25114,但是解密的可能结果有很多种!”
A:“你还是too young! 你觉得有哪些解呢?’BEAAD’? ‘YAAD’? ‘YAN’? ‘YKD’? 还是 ‘BEKD’? 都不是正确的单词吧?所以最后你还是会觉得我发给你的结果是’BEAN’,对吧?”
B:“是啦是啦,我的例子不好啦,但是如果你发了一条长达5000的字符串,将会有一大坨的解密方法啊?至少会有2种方法可行吧?”
A:“多少种呢?”
B:“让ACM选手解决吧!”

输入

有多组数据,每组数据一行一个数字串,长度不超过5000,而且是某一个字符串的加密结果,数字间没有空格。一行输入:‘0’表示输入结束。

输出

对于每组数据,输出一行一个正整数,表示可能的解密方案的数量,结果保证在long long内。

样例输入

25114
1111111111
3333333333
0

样例输出

6
89
1

题解

本题可能会有一些小坑,比如01不能被解密为’A’,单个数字0没有对应字符,所以处理的时候要特别注意一下。

本题显然是个动态规划题,因为某位看成一位数字还是和前面一位数字合在一起看成二位数字,都不影响后面的状态。
dp[i]表示到第i位的可能解的个数。显然有如下的方程:
dp[i]=dp[i-1](*1)+dp[i-2](*2)

(*1) digits[i]不为0,转移表示第i位单独解析为一个字母,当然没有对应0的字母。
(*2) 合并digits[i]和digits[i-1]后不超过26,digits[i-1]不为0,因为01不表示A,超过26显然不对应字母。

代码

#include <cstdio>
#include <cstring>
#define FOR(i,j,k) for(i=j;i<=k;++i)
const int N = 10005;
char digits[N];
long long dp[N];
int main() {
    int i, len;
    while (scanf("%s", digits + 1) == 1) {
        len = strlen(digits + 1);
        if (len == 1 && digits[1] == '0') break;

        FOR(i,1,len) digits[i] -= '0';

        dp[0] = dp[1] = 1;
        FOR(i,2,len) {
            if (digits[i] == 0) dp[i] = 0;
            else dp[i] = dp[i - 1];
            if (digits[i - 1] == 2 && digits[i] > 6) continue;
            if (digits[i - 1] > 2 || digits[i - 1] == 0) continue; // 01 is not A.
            dp[i] += dp[i - 2];
        }
        printf("%lld\n", dp[len]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值