这是 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;
}