有n个柱子,现在要给柱子染色,有k种颜色可以染,求有多少种染色方案

有n个柱子,现在要给柱子染色,有k种颜色可以染,求有多少种染色方案_第1张图片

这是 www.lintcode.com 上面的 第514道题

有n个柱子,现在要给柱子染色,有k种颜色可以染,求有多少种染色方案?

题目要求说,不存在超过2个相邻的柱子颜色相同

思路::::

 当 只有 1 个柱子的时候                k 种染色方案

当 有2 个柱子的时候                    k*k 中染色方案

当 有 3 个柱子的时候  分析如下

        情况一: 前两个柱子颜色相同,那么第三个柱子颜色必须与前两个不一样 

                    //      k种可能                               ( k-1) 种可能                   k * ( k-1 )                                                                

        情况二:  前两个柱子颜色不同,那么第三个柱子颜色无所谓  因为题目中是不超过两个连续相同颜色,两个柱子颜色相同是被允许的。 

                      //      k*k  种可能                        ( k-1) 种可能                   k * k * (k-1)

所以  3 个柱子染色方案 是      k * ( k-1 )  + k * k * (k-1)

情况一,前两个柱子颜色相同 ,有 k 种可能  ,也就相当于  只有一个柱子

情况二,前两个柱子颜色不同, 有k*k 种可能, 也就相当于  只有两个柱子

这里我们  可以假定  公式为    D(n)  =  (k-1) * D(n-1) + (k-1)*D(n-2)


现在情况推展到   n  为很大一个数字                  

  p ............   p   p   p  p  p   p   p   p   p   p  p   p   p   p

   这里有 n-1 个染好色  p ,并且符合题目要求, 我们要给第  n 个  “p” 染色

    那么  第 n-2  个p  和第 n-1 个 p  只有两种情况  要么颜色相同,要么不同

   因为我们事先假定前  n-1 个p 符合题目染色要求

设  n-2 个  p 染色 方案  D(n-2)

      n-1 个  p 染色 方案  D(n-1)

    如果  第n-1个p 和第n-2个p颜色相同,  那么 第n个柱子 有k-1种染色法,

    这种情况   D(n-2)* (k-1), 因为  n-1,n-2颜色相同,和  只有  n-2个  柱子没有区别

    如果  第n-1个p 和第n-2个p颜色不同,  那么第n个柱子 有(k -1)种染色法,(它前面两个柱子那种颜色不可以所以是k-1)这种情况 D(n-1)* (k-1), 因为  n-1,n-2颜色相同

综上    公式为  D(n)  =  (k-1) * D(n-1) + (k-1)*D(n-2)


第一份代码   超时了,下面有优化的代码

#include 
using namespace std;

class Solution {
    public:
        int numWays(int n, int k) {
            // write your code here
            if( n == 1 )return k;
            if( n == 2 )return k*k;
            return numWays(n-1,k)*(k-1) + numWays(n-2,k)*(k-1);
        }
};
int main()
{
    int a = 3, b = 2;
    Solution* ss = new Solution();
    cout<numWays(a, b);
    return 0;
}

这种方法  使用了递归  但是重复的值计算太多遍,比如  计算  第99项  需要(第98, 97项)

但是  第98项  又要计算第(97,96)项,然后   第97项还是要计算  第96项  超时


第二份代码

#include 
using namespace std;
class Solution {
    public:
        int numWays(int n, int k) {
            // write your code here
            int a = k;    //  这是 n = 1 时候的答案
            int b = k*k;   //  这是 n = 2 时候的答案
            int t = (n-1)/2;    
            for(int i = 0; i < t ;++i){
                a = a * (k-1) + b * (k-1);
                b = b * (k-1) + a * (k-1);
            }                                    //通过这个循环  第一个循环 得到了  n = 3,4 时的答案
            if( n % 2 == 0  ){                   //              第二个循环 得到了  n = 5,6 时的答案
                return b;
            }else{
                return a;
            }
        }
};

int main()
{
    int a = 3, b = 2;
    Solution* ss = new Solution();
    cout<numWays(a, b);
    return 0;
}







你可能感兴趣的:(有n个柱子,现在要给柱子染色,有k种颜色可以染,求有多少种染色方案)