codility上的问题(18) Rho 2012

从正整数1开始,产生一个数列,数列中的每个数是之前出现过的任意两个数的和(可以相等),问产生正整数A,需要的数列长度至少是多少?返回这样一个最短的序列。

例如A=42 可以这样[1, 2, 3, 6, 12, 24, 30, 42],也可以[1, 2, 4, 5, 8, 16, 21, 42],后者是最短的。A不大于600。


分析: 本题没规定时间、空间复杂度。因为本题只能暴力搜索,但是一般的实现会超时,需要一些剪枝。首先保证数列严格单增。另外,我们用迭代加深dfs做的时候,注意看一下剩余的长度能不能达到所要找的数,判断的方法很简单,达到一个数最快的方法是,每次把最大的翻倍……另外可以估算下序列的长度不超过2*logA,因为我们可以按2进制位把A需要的那些2^n都产生出来,再加出A……代码没啥好说的……


代码:

 

// you can also use includes, for example:



// #include <algorithm>











bool dfs(int A,vector<int> &v,int length) {



    if (v.back() == A) {



        return true;



    }



    if (v.size() >= length) {



        return false;



    }



    int i,j, x;



    for (i = v.back(), j = length - v.size(); (i < A) && (j); i <<= 1, --j)



    ;



    if (i < A) {



        return false;



    }



    for (i = v.size() - 1; (i >= 0) && (v[i] << 1) > v.back(); --i) {



        for (j = i; (j >= 0) && ((x = v[i] + v[j]) > v.back()); --j) {



            if (x <= A) {



                v.push_back(x);



                if (dfs(A, v, length)) {



                    return true;



                }



                v.pop_back();



            }



        }



    }



    return false;



}



        



    



vector<int> solution(int A) {



    // write your code here...



vector<int> v;



int i;



    v.push_back(1);



    for (i = 1; !dfs(A, v, i); ++i)



        ;



    return v;



}


 


 

你可能感兴趣的:(2012)