LIntCode 1444: Dyeing Problem (DP 好题)

1444. Dyeing Problem

There is a circle, divided into n sectors. All the sectors are colored with some of m colors. The colors of adjacent sectors cannot be the same. Find the total number of plans.

 

Example

Example 1:

 

Input:n = 2,m = 3

Output:6

Explanation:One circle is divided into two sectors. There are six kinds of schemes for coloring in three colors: black, red, black and white, white and red, white and black, red and white, and red and black.

Example 2:

 

Input:n = 3,m = 2

Output:0

Explanation:A circle is divided into 3 sectors and colored with 2 colors. No matter how it is colored, there is no guarantee that the adjacent colors are different.          

Notice

Do not consider symmetry.

Since this number may be large, you only need to return the solution number mod 1e9 + 7.

1 \leq n \leq 10^5

​1 \leq m \leq 10^5

​​解法1:DP
dp[i]表示有i个sector的圆能构成的plan总数。那么当i>=4时,dp[i]有2种可能:
1) i-1个sector的圆的第一个sector和最后一个sector同色,此时这i-1个sector所构成的plan总数就是dp[i-2]。注意,根据题目首尾不能同色,所以这种情况就是dp[i - 2],跟dp[i-1]没关系。第i个sector有m-1种可能,因为是往2个同色的sector中间插入。
2) i-1个sector的圆的第一个sector和最后一个sector不同色,此时这i-1个sector所构成的plan总数就是dp[i-2]。第i个sector有m-2种可能,因为是往2个不同色的sector中间插入。

class Solution {
public:
    /**
     * @param n: the number of sectors
     * @param m: the number of colors
     * @return: The total number of plans.
     */
    int getCount(int n, int m) {
        //dp[i] is the total # of plans with a circle with i sectors
        vector<int> dp(n + 1, 0);
        dp[1] = m;
        dp[2] = (long) dp[1] * (m - 1) % 1000000007;
        dp[3] = (long) dp[2] * (m - 2) % 1000000007;
        
        for (int i = 4; i <= n; ++i) {
            //if the first sector and the last sector are same color
            dp[i] = (long) dp[i - 2] * (m - 1) % 1000000007;

            //if the first sector and the last sector are not same color
            dp[i] += (long) dp[i - 1] * (m - 2) % 1000000007;
            dp[i] %= 1000000007;
        }
        
        return dp[n];
    }
};

解法2:解法1+滚动数组优化

class Solution {
public:
    /**
     * @param n: the number of sectors
     * @param m: the number of colors
     * @return: The total number of plans.
     */
    int getCount(int n, int m) {
        //dp[i] is the total # of plans with a circle with i sectors
        vector<int> dp(3, 0);
        dp[1] = m;
        dp[2] = (long) dp[1] * (m - 1) % 1000000007;
        dp[0] = (long) dp[2] * (m - 2) % 1000000007;  // 0 = 3 % 3
        
        for (int i = 4; i <= n; ++i) {
            //if the first sector and the last sector are same color
            dp[i % 3] = (long) dp[(i - 2) % 3] * (m - 1) % 1000000007;

            //if the first sector and the last sector are not same color
            dp[i % 3] += (long) dp[(i - 1) % 3] * (m - 2) % 1000000007;
            dp[i % 3] %= 1000000007;
        }
        
        return dp[n % 3];
    }
};

解法3:滚动数组另一个版本。
 

class Solution {
public:
    /**
     * @param n: the number of sectors
     * @param m: the number of colors
     * @return: The total number of plans.
     */
    int getCount(int n, int m) {
        int third = m;
        int first = (long) third * (m - 1) % 1000000007;
        int second = (long) first * (m - 2) % 1000000007;
        
      //  if (n == 1) return third;
        if (n == 2) return first;
        if (n == 3) return second;

        for (int i = 4; i <= n; ++i) {
            //if the first sector and the last sector are same color
            third = (long) first * (m - 1) % 1000000007;

            //if the first sector and the last sector are not same color
            third += (long) second * (m - 2) % 1000000007;
            third %= 1000000007;
            first = second;
            second = third;
        }
        
        return third;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值