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++ 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 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 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# 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 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.