【问题标题】:Dynamic programming - paint fence algorithm动态规划——油漆栅栏算法
【发布时间】:2015-12-03 08:10:26
【问题描述】:

n 个帖子的栅栏,每个帖子都可以用 k 种颜色中的一种进行绘制。您必须绘制所有柱子,以使不超过两个相邻的栅栏柱具有相同的颜色。返回绘制栅栏的方法总数。

diff - 不同颜色的组合数,
same - 相同颜色的组合数,
n -帖子数,
k - 颜色数。

对于 n = 1:

diff = k;
same = 0;

对于 n = 2:

diff = k * (k - 1);
same = k;

对于 n = 3:

diff = (k + k * (k - 1)) * (k - 1);
same = k * (k - 1);

最后的公式是:

diff[i] = (diff[i - 1] + diff[i - 2]) * (k - 1);
same[i] =  diff[i - 1];

我知道如何找到same[i],但我不知道如何找到diff[i]。你能解释一下diff[i] 的公式吗?

【问题讨论】:

    标签: algorithm dynamic-programming combinatorics


    【解决方案1】:
    total[i] = diff[i] + same[i]   (definition)
    
    diff[i] = (k - 1) * total[i-1]
            = (k - 1) * (diff[i-1] + same[i-1])
            = (k - 1) * (diff[i-1] + diff[i-2])
    

    【讨论】:

      【解决方案2】:

      这是一个组合学论证。

      diff[i, c] 是根据问题陈述的规则绘制i 帖子的方法数,使得最后一个栅栏被涂上颜色c

      我们有:

      diff[i, c] = diff[i - 1, c'] + diff[i - 2, c''], c' != c OR c'' != c
      

      对于我们绘制i的每个c,前一个可以以c' != c结尾(在这种情况下,我们不关心第二个前一个是什么),或者第二个前一个可以以一个结尾c'' != c(在这种情况下,我们不关心前一个是什么),或者两者兼而有之。

      k - 1 可能是 c' != ck - 1 可能是 c'' != c。所以我们可以从循环中删除c,然后简单地写:

      diff[i] = (k - 1) * (diff[i - 1] + diff[i - 2])
      

      你有什么。

      【讨论】:

      • 公式中的小错别字,第二个diff[i-1]应该是diff[i-2]
      • 很有教育意义的解释。如果我在面试中提出这个问题,我可能会这样做:1)最后2个帖子的颜色相同,因此最后2个帖子不能与最后3个相同。 (k-1) * diff[n-2] 2) 最后 2 个帖子有不同的颜色。 (k-1) * diff[n-1] 它们一起构成 (k-1) * (diff[n-2] + diff[n - 1])
      【解决方案3】:

      解决方案涉及详细解释。请务必看一看。

      public class PaintingFence {
      
        public static int paintFence(int n, int k) {
          //if there is 0 post then the ways to color it is 0.
          if(n == 0) return 0;
      
          //if there is one 1 post then the way to color it is k ways.
          if(n == 1) return k;
      
          /**
           * Consider the first two post.
           * case 1. When both post is of same color
           *    first post can be colored in k ways.
           *    second post has to be colored by same color.
           *    So the way in which the first post can be colored with same color is k * 1.
           *
           * case 2. When both post is of diff color
           *    first post can be colored in k ways.
           *    second post can be colored in k-1 ways.
           *    Hence the ways to color two post different is k * (k - 1)
           */
          int same = k * 1;
          int diff = k * (k -1);
      
          /**
           * As first 2 posts are already discussed, we will start with the third post.
           *
           * If the first two post are same then to make the third post different, we have
           * k-1 ways. Hence same * (k-1)
           * [same=k, so same * k-1 = k*(k-1) = diff => Remember this.]
           *
           * If the first two posts are different then to make the third different, we also have
           * k - 1 ways. Hence diff * (k-1)
           *
           * So to make third post different color, we have
           *  same * (k-1) + diff * (k-1)
           *  = (same + diff) * (k-1)
           *  = k-1 * (same + diff)
           */
          for(int i=3;i <=n; i++) {
            int prevDiff = diff;
            diff = (same + diff) * (k - 1); //as stated above
      
            /**
             * to make the third color same, we cannot do that because of constraint that only two
             * posts can be of same color. So in this case, we cannot have to same color so it has to be
             * diff.
             */
            same = prevDiff * 1;
          }
      
          return same + diff;
        }
      
        public static void main(String[] args) {
          System.out.println(paintFence(2, 4));
          System.out.println(paintFence(3, 2));
        }
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-03-26
        • 2013-11-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多