栅栏染色

题目来源:http://www.lintcode.com/zh-cn/problem/paint-fence/

题目描述

有一个栅栏,它有n个柱子,现在要给柱子染色,有k种颜色可以染。不能有连续三个柱子颜色相同,求有多少种染色方案。(lintcode描述错误)

翻译

任何一个柱子的颜色,只与它上一个柱子和上上个柱子的颜色有关。假设有柱子1,2,3

  1. 如果1和2的颜色相同,那么3的颜色必须和1,2不同;
  2. 如果1和2的颜色不同,那么3的颜色就与1和2没关系了;

样例

n = 3, k = 2, return 6

      post 1,   post 2, post 3
way1    0         0       1 
way2    0         1       0
way3    0         1       1
way4    1         0       0
way5    1         0       1
way6    1         1       0

思路 = 动态规划

第一个柱子的染色方案有:dp[1] = k

第二个柱子的染色方案有:dp[2] = k * k

第三个柱子的染色方案:

  1. 如果第三个柱子和第二个柱子颜色相同,那么第一个柱子肯定与二,三颜色不同,则染色方案有dp[1] * (k - 1);
  2. 如果第三个柱子和第二个柱子颜色不同,则与第一个柱子颜色无关,则染色方案有dp[2] * (k - 1);

第四个柱子的染色方案:

  1. 如果第四个柱子和第三个柱子颜色相同,那么第二个柱子肯定与三,四颜色不同,则染色方案有dp[2] * (k - 1);
  2. 如果第四个柱子和第三个柱子颜色不同,则与第二个柱子颜色无关,则染色方案有dp[3] * (k - 1);

第n个柱子的染色方案

  1. 如果第n个柱子和第n-1个柱子颜色相同,那么第n-2个柱子肯定与n-1,n颜色不同,则染色方案有dp[n-2] * (k - 1);
  2. 如果第n个柱子和第n-1个柱子颜色不同,则与第n-2个柱子颜色无关,则染色方案有dp[n-1] * (k - 1);

由以上可以得出状态转移方程:dp[n] = (dp[n - 1] + dp[n - 2]) * (k - 1)

code

class Solution {
public:
    /**
     * @param n non-negative integer, n posts
     * @param k non-negative integer, k colors
     * @return an integer, the total number of ways
     */
    int numWays(int n, int k) {
        // Write your code here
        if (n <= 0 || k <= 0) {
            return 0;
        }
        if (n == 1) {
            return k;
        }
        if (n > 2 && k == 1) { //  多个栅栏,但是k = 1
            return 0;
        }
        int n1 = k;
        int n2 = k * k;
        for (int i = 2; i < n; i++) {
            int tmp = n1 * (k-1) + n2 * (k - 1);
            n1 = n2;
            n2 = tmp;
        }
        return n2;
    }
};

请尊重作者的劳动,转载请注明作者及原文地址(http://blog.csdn.net/lis_12/article/details/55212759).

如果觉得本文对您有帮助,请点击‘顶’支持一下,您的支持是我写作最大的动力,谢谢。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值