Open In App

Word Wrap problem ( Tabulation Approach )

Last Updated : 07 Mar, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given an array arr[] of size n, where arr[i] denotes the number of characters in one word. Let k be the limit on the number of characters that can be put in one line (line width). Put line breaks in the given sequence such that the lines are printed neatly.
Assume that the length of each word is smaller than the line width. When line breaks are inserted there is a possibility that extra spaces are present in each line. The extra spaces include spaces put at the end of every line except the last one

The task is to minimize the following total cost where total cost = Sum of cost of all lines, where the cost of the line is = (Number of extra spaces in the line)2.

Examples:

Input: arr[] = [3, 2, 2, 5], k = 6
Output: 10
Explanation: Given a line can have 6 characters,
Line number 1: From word no. 1 to 1
Line number 2: From word no. 2 to 3
Line number 3: From word no. 4 to 4
So total cost = (6-3)2 + (6-2-2-1)2 = 32+12 = 10. As in the first line word length = 3 thus extra spaces = 6 – 3 = 3 and in the second line there are two words of length 2 and there is already 1 space between the two words thus extra spaces = 6 – 2 -2 -1 = 1. As mentioned in the problem description there will be no extra spaces in the last line. Placing the first and second words in the first line and the third word on the second line would take a cost of 02 + 42 = 16 (zero spaces on the first line and 6-2 = 4 spaces on the second), which isn’t the minimum possible cost.

Input: arr[] = [3, 2, 2], k = 4
Output: 5
Explanation: Given a line can have 4 characters,
Line 1: From word no. 1 to 1
Line 2: From word no. 2 to 2
Line 3: From word no. 3 to 3
Same explanation as above total cost = (4 – 3)2 + (4 – 2)2 = 5.

Please Refer Word Wrap Problem for recursive and memoization approaches.

Using Bottom-Up DP (Tabulation) - O(n^2) time and O(n) space

The recursive approach for the word wrapping problem involves trying all possible ways to place words on each line while ensuring that the total length of words (including spaces) does not exceed the line width k. For each valid configuration, we calculate the cost (squared extra spaces) of the current line and recursively solve the problem for the remaining words. The goal is to minimize the total cost across all lines.

We can build it’s recurrence relation as follow:
Let dp[i] represent the minimum cost to wrap words starting from the i-th word until the end. The goal is to calculate dp[0], which will give us the minimum cost to wrap the entire set of words.
For each index i,

  • dp[i] = min(cost(i, j) + dp[j+1]) for all j from i+1 to n-1 such that number of characters (including spaces) from i to j does not exceed k.

where,

  • cost(i, j) is the cost for wrapping words from index i to j in a single line.
  • dp[j+1] is the minimum cost for wrapping words from index j + 1 to the end.

Base Case:

When no words remain, the cost is 0:
dp[n] = 0

C++
// C++ program to minimize the cost to wrap the words
// using tabulation

#include <bits/stdc++.h>
using namespace std;

int solveWordWrap(vector<int> &arr, int k) {
    int n = arr.size();

    // Create a DP table to store the minimum
    // cost of word wrapping from index i
    // Initialize dp array with a large value
    vector<int> dp(n + 1, INT_MAX);

    // Base case: if no words remain, cost is 0
    dp[n] = 0;

    // Iterate over the array from right to left 
      // to fill the dp table
    for (int curr = n - 1; curr >= 0; curr--) {
        int sum = 0;

        // Try placing words from the current position to the next
        for (int i = curr; i < n; i++) {
          
            // Add the length of the current word
            sum += arr[i];

            // Total length including spaces between words
            int tot = sum + (i - curr);

            // If the total exceeds the line width, break out
           // of the loop
            if (tot > k)
                break;

            // If it's the last word, there's no cost (no extra
           // space after the last word)
            if (i == n - 1) {
                dp[curr] = min(dp[curr], 0);
            }
            else {
              
               // Calculate the cost for the current line and 
              // add the cost of the next lines
                int cost = (k - tot) * (k - tot);
                dp[curr] = min(dp[curr], cost + dp[i + 1]);
            }
        }
    }

    // Return the result which will be the minimum 
  // cost to wrap words starting from index 0
    return dp[0];
}

int main() {
    int k = 6;
    vector<int> arr = {3, 2, 2, 5};
    cout << solveWordWrap(arr, k) << endl;

    return 0;
}
Java
// Java program to minimize the cost to wrap the words.
// using tabulation

import java.util.*;

class GfG {

	static int solveWordWrap(int[] arr, int k) {
		int n = arr.length;

		// Create a DP table to store the minimum cost of
		// word wrapping from index i Initialize dp array
		// with a large value
		int[] dp = new int[n + 1];
		Arrays.fill(dp, Integer.MAX_VALUE);

		// Base case: if no words remain, cost is 0
		dp[n] = 0;

		// Iterate over the array from right to left to fill
		// the dp table
		for (int curr = n - 1; curr >= 0; curr--) {
			int sum = 0;

			// Try placing words from the current position
			// to the next
			for (int i = curr; i < n; i++) {

				// Add the length of the current word
				sum += arr[i];

				// Total length including spaces between
				// words
				int tot = sum + (i - curr);

				// If the total exceeds the line width,
				// break out of the loop
				if (tot > k)
					break;

				// If it's the last word, there's no cost
				// (no extra space after the last word)
				if (i == n - 1) {
					dp[curr] = Math.min(dp[curr], 0);
				}
				else {

					// Calculate the cost for the current
					// line and add the cost of the next
					// lines
					int cost = (k - tot) * (k - tot);
					dp[curr] = Math.min(dp[curr],
					                    cost + dp[i + 1]);
				}
			}
		}

		// Return the result which will be the minimum cost
		// to wrap words starting from index 0
		return dp[0];
	}

	public static void main(String[] args) {
		int k = 6;
		int[] arr = { 3, 2, 2, 5 };

		System.out.println(solveWordWrap(arr, k));
	}
}
Python
# Python program to minimize the cost to wrap the words.
# using tabulation
 
def solveWordWrap(arr, k):
    n = len(arr)

    # Create a DP table to store the minimum cost of 
    # word wrapping from index i
    # Initialize dp array with a large value
    dp = [float('inf')] * (n + 1)

    # Base case: if no words remain, cost is 0
    dp[n] = 0

    # Iterate over the array from right to left to fill
    # the dp table
    for curr in range(n - 1, -1, -1):
        sumChars = 0

        # Try placing words from the current position to
        # the next
        for i in range(curr, n):
          
            # Add the length of the current word
            sumChars += arr[i]

            # Total length including spaces between words
            total = sumChars + (i - curr)

            # If the total exceeds the line width, break 
            # out of the loop
            if total > k:
                break

            # If it's the last word, there's no cost (no 
            # extra space after the last word)
            if i == n - 1:
                dp[curr] = min(dp[curr], 0)
            else:
              
                # Calculate the cost for the current line
                # and add the cost of the next lines
                cost = (k - total) ** 2
                dp[curr] = min(dp[curr], cost + dp[i + 1])

    # Return the result which will be the minimum cost to
    # wrap words starting from index 0
    return dp[0]


if __name__ == "__main__":
    k = 6
    arr = [3, 2, 2, 5]
    res = solveWordWrap(arr, k)
    print(res)
C#
// C# program to minimize the cost to wrap the words.
// using tabulation

using System;

class GfG {

    static int solveWordWrap(int[] arr, int k) {
        int n = arr.Length;

        // Create a DP table to store the minimum cost of
        // word wrapping from index i Initialize dp array
        // with a large value
        int[] dp = new int[n + 1];
        for (int i = 0; i <= n; i++) {
            dp[i] = int.MaxValue;
        }

        // Base case: if no words remain, cost is 0
        dp[n] = 0;

        // Iterate over the array from right to left to fill
        // the dp table
        for (int curr = n - 1; curr >= 0; curr--) {
            int sumChars = 0;

            // Try placing words from the current position
            // to the next
            for (int i = curr; i < n; i++) {
              
                // Add the length of the current word
                sumChars += arr[i];

                // Total length including spaces between
                // words
                int total = sumChars + (i - curr);

                // If the total exceeds the line width,
                // break out of the loop
                if (total > k)
                    break;

                // If it's the last word, there's no cost
                // (no extra space after the last word)
                if (i == n - 1) {
                    dp[curr] = Math.Min(dp[curr], 0);
                }
                else {
                  
                    // Calculate the cost for the current
                    // line and add the cost of the next
                    // lines
                    int cost = (k - total) * (k - total);
                    dp[curr] = Math.Min(dp[curr],
                                        cost + dp[i + 1]);
                }
            }
        }

        // Return the result which will be the minimum cost
        // to wrap words starting from index 0
        return dp[0];
    }

    static void Main() {
        int k = 6;
        int[] arr = { 3, 2, 2, 5 };
         int res = solveWordWrap(arr, k);
        Console.WriteLine(res);
    }
}
JavaScript
// JavaScript program to minimize the cost to wrap the
// words using tabulation

function solveWordWrap(arr, k) {
    const n = arr.length;

    // Create a DP table to store the minimum cost of word
    // wrapping from index i Initialize dp array with a
    // large value
    const dp = new Array(n + 1).fill(Number.MAX_VALUE);

    // Base case: if no words remain, cost is 0
    dp[n] = 0;

    // Iterate over the array from right to left to fill the
    // dp table
    for (let curr = n - 1; curr >= 0; curr--) {
        let sum = 0;

        // Try placing words from the current position to
        // the next
        for (let i = curr; i < n; i++) {
        
            // Add the length of the current word
            sum += arr[i];

            // Total length including spaces between words
            const total = sum + (i - curr);

            // If the total exceeds the line width, break
            // out of the loop
            if (total > k)
                break;

            // If it's the last word, there's no cost (no
            // extra space after the last word)
            if (i === n - 1) {
                dp[curr] = Math.min(dp[curr], 0);
            }
            else {
            
                // Calculate the cost for the current line
                // and add the cost of the next lines
                const cost = (k - total) * (k - total);
                dp[curr]
                    = Math.min(dp[curr], cost + dp[i + 1]);
            }
        }
    }

    // Return the result which will be the minimum cost to
    // wrap words starting from index 0
    return dp[0];
}

const k = 6;
const arr = [ 3, 2, 2, 5 ];
const res = solveWordWrap(arr, k);
console.log(res);

Output
10

Time Complexity: O(n^2) 
Auxiliary Space: O(n), since n extra space has been taken.


Next Article

Similar Reads