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

你可能感兴趣的:(算法,动态规划)