Painting Fence Algorithm In C++ - C++ Programming Tutorial
C++ Course / STL Algorithm / Painting Fence Algorithm In C++

Painting Fence Algorithm In C++

BLUF: Mastering Painting Fence Algorithm In C++ is a critical step in becoming a proficient C++ developer. This lesson provides a deep dive into the syntax, performance considerations, and real-world applications of this concept.
Key Performance Insight: Painting Fence Algorithm In C++

C++ is renowned for its efficiency. Learn how Painting Fence Algorithm In C++ enables low-level control and high-performance computing in the tutorial below.

However, the Fence Painting Algorithm presents itself as a compelling and achievable challenge within the realm of competitive programming and algorithm development. This particular problem revolves around determining the various methods of painting a fence with a set number of posts using a specific range of colors, all while adhering to the problem's constraints. Not only is this problem a common fixture in collections of dynamic programming tasks, but it also holds significance in numerous practical applications where sequences and color restrictions play a crucial role.

Suppose you are tasked with painting a fence containing n posts using k different colors. The objective is to arrange the posts in a way that ensures no two adjacent posts have the same color, and at most two posts of the same color are next to each other. While this requirement is straightforward, it introduces a complexity that makes direct methods impractical for large values of 'n' and 'k'. Therefore, a more effective strategy is essential for addressing this challenge.

The Painting Fence Algorithm does this, or rather, it follows the hallmarks of a dynamic programming algorithm: The process of splitting a problem into smaller ones and solving each of those problems only once, storing the results so that they can be used to help with future problem-solving. It also helps in minimizing the computational load while at the same time honing the solution towards scalability.

  • Now let's illustrate the Painting Fence Algorithm by breaking it down to what it is. For a simpler example, let's have three fence posts and two colors. You could begin by painting the first post to either of the two colors. The second post should consider the color of the first post in order to be of a different color. The complexity rises step-by-step for the subsequent posts because the algorithm receives two previous colors with which it has to adhere to the constraints.
  • This problem of dynamic programming the way can be interpreted through recursion. For instance, if you denote the number of ways to paint n posts where the last two posts have different colors as diff(n) and the number of ways where the last two posts have the same color as same(n), you can derive the total ways to paint n posts using the relation: total(n) = diff(n) + same(n).
  • In this blog post, let us first carefully understand the problem statement of the painting fence algorithm before looking at the actual code of its solution in C++, which we'll be discussing further in detail. Here, we will use a simple step-by-step approach, which not only explains each and every step of the algorithm but also provides the code snippets for each step. Further, we will explain how complex the algorithm is and the real-life use of this concept, along with examples. In conclusion, we will grasp the Painting Fence Algorithm and find it a useful tool in solving sequence arrangement problems quickly at the end of this post.
  • Mathematical Basis:

The Fence Painting Algorithm presents an intriguing mathematical concept by integrating elements of combinatorics and dynamic programming. This problem involves determining the various ways to paint a maximum of two adjacent fence posts using k different colors. This specific constraint adds a level of intricacy that necessitates prompt calculation of results.

Put differently, from a mathematical perspective, the solutions entail employing recursive relationships to merge fundamental solutions to a particular problem by deconstructing it into more manageable subproblems.

If dp[n] denotes the count of ways to paint n posts, the algorithm leverages recurrence relations like: If dp[n] signifies the count of ways to paint n posts, the algorithm utilizes recurrence relations such as:

Example

dp[n]=(k−1)×(dp[n−1]+dp[n−2])
  • This approach to solving the problem is known as Dynamic Programming since it involves the optimization of the solution space that has been broken down into sub-problems, and the results of these sub-problems are stored
  • Hence, if the same sub-problem occurs again, the result does not have to be calculated instead it can be retrieved from the stored results, and in this way, this task of solving the problem takes linear time. This makes the algorithm interesting from a theoretical perspective as well as from a practical point of view, suitable for large-scale applications.
  • Problem Statement:

The challenge presented by the Painting Fence dilemma is to determine the total number of options available for painting a fence that consists of n posts using k different colors while ensuring that adjacent posts are not of the same color. In this scenario, n represents the quantity of posts in the fence, while k indicates the variety of colors that can be utilized. The problem description specifies that the unique painting configurations of the fence are defined as the various methods of coloring the fence in a manner where no three consecutive posts share the identical color.

Suppose you have a lengthy fence with numerous posts, and you aim to create an aesthetically pleasing color scheme. However, you face a restriction that prohibits having three consecutive sections with identical colors, adding complexity to the task.

The problem statement can be summarized as follows:

  • Supposing there are n fence posts and k colors to paint the fence with, how many different ways can the fence be painted?
  • Every post can be colored with one of the given colors.
  • More than two consecutive posts cannot be of the same color.

This challenge offers both mathematical enjoyment and practical relevance in various domains like architecture, design, scheduling, and others that involve arranging items with limitations. Our strategy for addressing this challenge involves employing dynamic programming to pinpoint subproblems and resolve them in the most optimal manner.

Approach 1: Dynamic Programming

Example

#include <iostream>
#include <vector>
 
using namespace std;
 
// Function to count the number of ways to paint the fence and return the dp array
int countWays(int n, int k, vector<int>& dp) {
    if (n == 0) return 0;
    if (n == 1) return k;
    
    dp[1] = k;
    dp[2] = k * k;
    
    // Fill the dp array using the relation
    for (int i = 3; i <= n; i++) {
        dp[i] = (k - 1) * (dp[i - 1] + dp[i - 2]);
    }
    
    return dp[n];
}
 
int main() {
    int n;  // Number of posts
    int k;  // Number of colors
    
    // Prompt user for input
    cout << "Enter the number of posts: ";
    cin >> n;
    cout << "Enter the number of colors: ";
    cin >> k;
    
    // Validate inputs
    if (n <= 0 || k <= 0) {
        cout << "Invalid input. The number of posts and colors must be positive integers." << endl;
        return 1;
    }
    
    // Initialize a dp array to store the number of ways to paint each post
    vector<int> dp(n + 1, 0);
    
    // Call the function and display the result
    int result = countWays(n, k, dp);
    cout << "Number of ways to paint the fence: " << result << endl;
    
    // Additional output to understand the DP array (for debugging or educational purposes)
    cout << "DP array contents: ";
    for (int i = 0; i <= n; ++i) {
        cout << dp[i] << " ";
    }
    cout << endl;
    
    return 0;
}

Output:

Output

Enter the number of posts: 5 
Enter the number of colors: 3 
Number of ways to paint the fence: 180 
DP array contents: 0 3 9 24 66 180

Approach 2: Optimized Dynamic Programming (Space Optimized)

Example

#include <iostream> 
#include <vector> 
using namespace std; 
  
// Function to count the number of ways to paint the fence using space optimization 
int countWaysOptimized(int n, int k) { 
if (n == 0) return 0; 
if (n == 1) return k; 
     
// Initialize variables to store previous values 
int prev2 = k; 
int prev1 = k * k; 
     
// Compute the number of ways for each post from 3 to n 
for (int i = 3; i <= n; i++) { 
int current = (k - 1) * (prev1 + prev2); 
prev2 = prev1; 
prev1 = current; 
} 
     
return prev1; 
} 
  
int main() { 
int n;  // Number of posts 
int k;  // Number of colors 
     
// Prompt user for input 
    cout << "Enter the number of posts: "; 
    cin >> n; 
    cout << "Enter the number of colors: "; 
    cin >> k; 
  
// Validate inputs 
if (n <= 0 || k <= 0) { 
        cout << "Invalid input. The number of posts and colors must be positive integers." << endl; 
return 1; 
} 
     
// Call the function and display the result 
int result = countWaysOptimized(n, k); 
    cout << "Number of ways to paint the fence: " << result << endl; 
  
// Additional output to show the process 
vector<int> ways; 
int prev2 = k; 
int prev1 = k * k; 
    ways.push_back(prev2); 
    ways.push_back(prev1); 
     
for (int i = 3; i <= n; i++) { 
int current = (k - 1) * (prev1 + prev2); 
prev2 = prev1; 
prev1 = current; 
        ways.push_back(current); 
} 
  
// Display intermediate values 
    cout << "Intermediate values: "; 
for (int val : ways) { 
        cout << val << " "; 
} 
    cout << endl; 
  
return 0; 
}

Output:

Output

Enter the number of posts: 5 
Enter the number of colors: 3 
Number of ways to paint the fence: 180 
Intermediate values: 3 9 24 66 180

Time Complexity

Approach 1:

The first approach involves the use of a dp table where dp[i] represents the number of ways to paint n posts. Here's a brief breakdown of the steps involved:

  • Initialization: In the dp array, we set initial conditions, which are the base cases. dp[1] is set to k because there are k ways to paint the first post, and dp[2] is set to k×k because each of the k ways to paint the first post can pair with k ways to paint the second post.
  • Iteration: We use for loop starting from i=3 to i=n. For each i, we compute dp[i] using the relation dp[i] = (k - 1) \times (dp[i - 1] + dp[i - 2]). In simple terms, we are using the Fibonacci sequence to find the number of ways in which k objects can be placed in n baskets.
  • The iteration loop runs n−2 times (from 3 to n), and for each iteration, we simply perform constant time operations. Hence, the time complexity of this method can be said to be O(n).
  • Approach 2:

The second approach minimizes the space complexity with just two variables, namely prev1 and prev2, instead of the array to store the last two values used in the computation. Here's how this approach works:

  • Initialization: Thus, we set prev2 = k, prev1 = k×k, meaning the number of ways to paint 1 and 2 posts.
  • Iteration: We can iterate it through i=3 to i=n. For each iii, we calculate the current number of ways with current = (k - 1) \times (prev1 + prev2) and update the prev2 and prev1.
  • Once again, the main loop goes n−2 times (from 3 to n), and all operations in the loop are constant time. Therefore, the time complexity of this approach is O(n) also.
  • Conclusion:

The Fence Painting Algorithm, alternatively referred to as the Painting Fence Algorithm, presents an effective challenge within the realm of dynamic programming and competitive programming. This task involves devising an efficient method to determine the possible ways to color a fence consisting of n posts with k colors, ensuring that no more than two adjacent posts share the same color. This scenario exemplifies the utility of dynamic programming in breaking down intricate issues into manageable subtasks, leading to optimized solutions for sizable datasets. Our scrutiny encompassed a pair of strategies for tackling this predicament. The initial method leverages a dynamic programming table to retain outcomes systematically, facilitating the computation of subsequent results in the future with a time complexity of O(n). Conversely, the second approach streamlines the space utilization by employing solely two variables to hold the last two calculated values, maintaining the time complexity at O(n).

Both methods effectively address the issue, demonstrating the efficiency of employing dynamic programming to handle computational tasks and scale operations. The Painting Fence Algorithm is not just a captivating concept but also finds practical use in diverse fields like design, architecture, and scheduling, where the limitation of sequences and colors is common in many scenarios. Therefore, gaining proficiency in this algorithm will expand an individual's problem-solving skills, providing an additional strategy for tackling a range of real-world challenges.

Input Required

This code uses input(). Please provide values below:

Logic Practice
Install Logic Practice
Add to home screen for a faster app-like experience