从物理学到计算机,再到硬件,再到人工智能!
蓝桥杯备赛 (LintCode上刷的第三题)
问题描述
我们有一个栅栏,它有n个柱子,现在要给柱子染色,有k种颜色可以染。
必须保证不存在超过2个相邻的柱子颜色相同,求有多少种染色方案。
样例输出
n = 3, k = 2, return 6
问题分析
最开始,我想用动态数组保存每一种方案的第i根柱子的颜色。后来发现这样数据量太大,而且记录也很困难。最后转换思路,用dp[i]表示到第i根柱子时有多少种涂色方案。这样就很容易就实现了。
dp[i]和dp[i + 1]表示分别到前面两根柱子时的涂色方案。
首先赋初值:dp[0] = k;dp[1] = k * k;
如果dp[i] == dp[i + 1],说明前面两根柱子颜色相同,则dp[i + 3] = (k - 1) * dp[i + 2];如果dp[i] != dp[i + 1],说明前面两根柱子颜色不相同,则dp[i + 3] = (k - 1) * dp[i + 1]。
因为此段时间一直在刷动态规划的题,所以一般都采用动态规划来求解!
JAVA实现代码
package DP;
public class PostColored514_1111 {
/**
* 根据不超过两个相邻柱子的颜色相同的规则,求出有多少中染色方案
* @param n 有多少根柱子
* @param k 有多少种颜色
* @return
*/
public static int postColored(int n, int k) {
// 没有柱子时,没有涂色方案
if (n == 0) {
return 0;
}
// 当只有一根柱子时,有多少种颜色就有多少种方案
if (n == 1) {
return k;
}
// 创建一个数组dp,dp[i]表示前i根柱子有多少种涂色方案
int[] dp = new int[n];
if (n == 2) {
return k * k;
} else {
// 第一根柱子有k种涂色方案
dp[0] = k;
//到第二根柱子,有k * k种染色方案
dp[1] = k * k;
//遍历剩下的柱子
for (int i = 2; i < n; i++) {
//当前两根柱子染色不同时,第三根柱子的染色情况为dp[i - 1] * (k - 1)
//当前两根柱子染色相同时,第三根柱子的染色情况为dp[i - 2] * (k - 1)
dp[i] = dp[i - 1] * (k - 1) + dp[i - 2] * (k - 1);
}
}
return dp[n - 1];
}
public static void main(String[] args) {
int n = 3, k = 2;
System.out.println(postColored(n, k));
}
}