寻找幸运数

问题描述:【来源于某次编程比赛】

小绿在纸上写下自己的号码,例如:12345,她未来爱人的号码长度与她的长度相同。 
第一位数字是介于0到9之间的任一个, 第二个数字是小绿写下的号码的第二位和刚刚写下的第一位数字和的一半。
 假设小绿写下第一位是9,算术平均值等于(2 + 9)/ 2 = 5.5。她可以根据自己的意愿向上或向下取整。
她选择数字5,将结果数字记下在其数字的第二个数字之后,小绿以相同方式寻找第三个数,即找到她的数字的第三个数字和刚算出来的第二个数字和的一半。
结果是(5 + 3)/ 2 = 4,在这情况下答案是唯一的。
因此,每个第i个数字被确定为小绿数的第i个数字和她的幸运数的第i - 1个数字的算术平均值。
如果需要,可以将数字四舍五入。 
例如,小绿可以从12345,算出95444。 但是她拨出电话后发现她错了。可能是因为四舍五入的时候出了错,或者给出的第一个数错了。
请编写代码根据给定的数,算出可能的幸运数字的总数

递归
递归方法:

/* s: 输入字符串 d: 生成的目的串  v:目的串最后一个字符的值
    x: 标识重复  y: 递归串 */
int G(string s, int v, string y, string d, int &x, vector<vector<int>> L)
{
    if (y == "") return 1;

    int N = 0, b = y[0] - '0', m = b + v, p = m / 2;
    string u = d + to_string(p + 1), w = d + to_string(p), r = y.substr(1);
    u == s || w == s ? x = 1 : 0;

    int l = r.size();
    L[p][l] == 0 ? L[p][l] = G(s, p, r, w, x, L) : 0;  N += L[p][l];
    if (m % 2 != 0)
        L[p + 1][l] == 0 ? L[p + 1][l] = G(s, p + 1, r, u, x, L) : 0; N += L[p + 1][l];
    return N;
}

调用方法:

int count_nums(string s) {
    int S = 0, x, len = s.size(); 
    vector<vector<int>> L(10,vector<int>(len));
    for (int i = 0; i <= 9; ++i)
        S += G(s, i, s.substr(1), to_string(i), x, L);
    return x == 1 ? S - 1 : S;
}

动态规划 - 二维数组
数组定义:h*10

long count_nums(string s)
{
    long S = 0, t = 1, h = s.size(), j, i, b, v, m, u;
    vector<vector<int>> L(h, vector<int>(10));
    for (i = 0; i <= 9; ++i) L[0][i] = 1;

    for (j = h - 1; j > 0; --j) {
        b = s[j] - '0';
        if (abs(s[j] - s[j - 1]) > 1) t = 0;

        for (i = 0; i <= 9; ++i) {
            m = b + i, v = m / 2, u = h - j;
            L[u][i] = L[u - 1][v];
            if (m % 2 == 1)  L[u][i] += L[u - 1][v + 1];
        }
    }

    for (i = 0; i <= 9; ++i) S += L[h - 1][i];
    return S - t;
}

动态规划 - 2个一维数组

long count_nums(string s)
{
    long S = 0, t = 1, h = s.size(), i, j = h - 1, b;
    vector<int> P(10, 1), L(10);
    for (; j > 0; --j) {
        b = s[j] - '0';
        if (abs(s[j] - s[j - 1]) > 1) t = 0; 

        for (i = 0; i <= 9; ++i) {
            L[i] = P[b / 2];
            if (b % 2 == 1)  L[i] += P[b / 2 + 1];
            ++b;
        }       
        P = L;
    }

    for (; j < 10; j++) S += L[j];
    return S - t;
}

Python版本-动态规划

def count_right_numbers(s):
    S=[int(i) for i in s[::-1]]
    a=S[0]
    t=1
    L=[1]*10
    for b in S:
        t &= -2<b-a<2
        P = L*1
        a=b
        for i in range(10):
            L[i]=sum(P[b//2:(b+3)//2])
            b+=1
    return sum(P)-t
posted @ 2019-12-03 20:44  万箭穿心,习惯就好。  阅读(209)  评论(0编辑  收藏  举报