给定一系列单词,并限制一行中可以输入的字符数(行宽)。按给定的顺序放置换行符,以使行被整齐地打印。假设每个单词的长度小于行宽。当插入换行符时,每行中都可能存在多余的空格。多余的空格包括除最后一行以外的每行末尾的空格。
问题是使以下总成本最小化。
总成本=所有行的成本总和,其中行的成本为=(行中多余空格的数量)^ 2。
例如,考虑以下字符串和线宽M = 15
“ Geeks for Geeks提出了自动换行问题”
以下是3行中单词的优化排列
极客换极客
提出词
包装问题
第1行和第2行的总额外空间为0和2。不考虑第3行的空间,因为它不是如上所述的额外空间。因此,总成本的最佳值为0 + 2 * 2 = 4。
例子:
Input format: Input will consists of array of integers where each array element represents length of each word of string. For example, for string S = "Geeks for Geeks", input array will be arr[] = {5, 3, 5}.
Output format: Output consists of a series of integers where two consecutive integers represent
starting word and ending word of each line.
Input : arr[] = {3, 2, 2, 5}
Output : 1 1 2 3 4 4
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
Input : arr[] = {3, 2, 2}
Output : 1 1 2 2 3 3
Line number 1: From word no. 1 to 1
Line number 2: From word no. 2 to 2
Line number 3: From word no. 3 to 3
推荐:在继续解决方案之前,请先在“实践”上解决它。
方法:我们讨论了基于动态编程的自动换行问题的解决方案。讨论的解决方案使用O(n ^ 2)辅助空间。可以将使用的辅助空间减小为O(n)。这个想法是使用两个一维数组dp []和ans [],其中dp [i]代表其中arr [i]是第一个单词,而ans [i]代表最后一个单词的索引行的最小开销在单词arr [i]是第一个单词的行中。令k代表每行中字符数的限制。假设对于任何l行,该行中的第一个单词都位于arr []中的索引i处。该行的最低成本存储在dp [i]中。该行的最后一个单词在arr []中的索引j处,其中j可以从i变为n。遍历j的所有值,并跟踪到目前为止在l行中添加的字符数。如果字符数少于k,则用这些字符数查找当前行的成本。将此成本与到目前为止在dp [i]中针对该行找到的最低成本进行比较,并相应地更新dp [i]和ans [i]。对i的每个值重复上述过程,1 <= i <= n。每行的开始和结束词将在索引i和索引ans [i]处,其中行l + 1的i的下一个值是ans [i] + 1。
执行:
C++
// C++ program for space optimized
// solution of Word Wrap problem.
#include
using namespace std;
// Function to find space optimized
// solution of Word Wrap problem.
void solveWordWrap(int arr[], int n, int k)
{
int i, j;
// Variable to store number of
// characters in given line.
int currlen;
// Variable to store possible
// minimum cost of line.
int cost;
// DP table in which dp[i] represents
// cost of line starting with word
// arr[i].
int dp[n];
// Array in which ans[i] store index
// of last word in line starting with
// word arr[i].
int ans[n];
// If only one word is present then
// only one line is required. Cost
// of last line is zero. Hence cost
// of this line is zero. Ending point
// is also n-1 as single word is
// present.
dp[n - 1] = 0;
ans[n - 1] = n - 1;
// Make each word first word of line
// by iterating over each index in arr.
for (i = n - 2; i >= 0; i--) {
currlen = -1;
dp[i] = INT_MAX;
// Keep on adding words in current
// line by iterating from starting
// word upto last word in arr.
for (j = i; j < n; j++) {
// Update number of characters
// in current line. arr[j] is
// number of characters in
// current word and 1
// represents space character
// between two words.
currlen += (arr[j] + 1);
// If limit of characters
// is violated then no more
// words can be added to
// current line.
if (currlen > k)
break;
// If current word that is
// added to line is last
// word of arr then current
// line is last line. Cost of
// last line is 0. Else cost
// is square of extra spaces
// plus cost of putting line
// breaks in rest of words
// from j+1 to n-1.
if (j == n - 1)
cost = 0;
else
cost = (k - currlen) * (k - currlen) + dp[j + 1];
// Check if this arrangement gives
// minimum cost for line starting
// with word arr[i].
if (cost < dp[i]) {
dp[i] = cost;
ans[i] = j;
}
}
}
// Print starting index and ending index
// of words present in each line.
i = 0;
while (i < n) {
cout << i + 1 << " " << ans[i] + 1 << " ";
i = ans[i] + 1;
}
}
// Driver function
int main()
{
int arr[] = { 3, 2, 2, 5 };
int n = sizeof(arr) / sizeof(arr[0]);
int M = 6;
solveWordWrap(arr, n, M);
return 0;
}
Java
// Java program for space
// optimized solution of
// Word Wrap problem.
import java.io.*;
class GFG
{
// Function to find space
// optimized solution of
// Word Wrap problem.
static void solveWordWrap(int arr[],
int n, int k)
{
int i, j;
// Variable to store
// number of characters
// in given line.
int currlen;
// Variable to store
// possible minimum
// cost of line.
int cost;
// DP table in which
// dp[i] represents
// cost of line starting
// with word arr[i].
int dp[] = new int[n];
// Array in which ans[i]
// store index of last
// word in line starting
// with word arr[i].
int ans[] = new int[n];
// If only one word is present
// then only one line is required.
// Cost of last line is zero.
// Hence cost of this line is zero.
// Ending point is also n-1 as
// single word is present.
dp[n - 1] = 0;
ans[n - 1] = n - 1;
// Make each word first
// word of line by iterating
// over each index in arr.
for (i = n - 2; i >= 0; i--)
{
currlen = -1;
dp[i] = Integer.MAX_VALUE;
// Keep on adding words in
// current line by iterating
// from starting word upto
// last word in arr.
for (j = i; j < n; j++)
{
// Update number of characters
// in current line. arr[j] is
// number of characters in
// current word and 1
// represents space character
// between two words.
currlen += (arr[j] + 1);
// If limit of characters
// is violated then no more
// words can be added to
// current line.
if (currlen > k)
break;
// If current word that is
// added to line is last
// word of arr then current
// line is last line. Cost of
// last line is 0. Else cost
// is square of extra spaces
// plus cost of putting line
// breaks in rest of words
// from j+1 to n-1.
if (j == n - 1)
cost = 0;
else
cost = (k - currlen) *
(k - currlen) +
dp[j + 1];
// Check if this arrangement
// gives minimum cost for
// line starting with word
// arr[i].
if (cost < dp[i])
{
dp[i] = cost;
ans[i] = j;
}
}
}
// Print starting index
// and ending index of
// words present in each line.
i = 0;
while (i < n)
{
System.out.print((i + 1) + " " +
(ans[i] + 1) + " ");
i = ans[i] + 1;
}
}
// Driver Code
public static void main (String[] args)
{
int arr[] = {3, 2, 2, 5};
int n = arr.length;
int M = 6;
solveWordWrap(arr, n, M);
}
}
// This code is contributed
// by anuj_67.
Python 3
# Python 3 program for space optimized
# solution of Word Wrap problem.
import sys
# Function to find space optimized
# solution of Word Wrap problem.
def solveWordWrap(arr, n, k):
dp = [0] * n
# Array in which ans[i] store index
# of last word in line starting with
# word arr[i].
ans = [0] * n
# If only one word is present then
# only one line is required. Cost
# of last line is zero. Hence cost
# of this line is zero. Ending point
# is also n-1 as single word is
# present.
dp[n - 1] = 0
ans[n - 1] = n - 1
# Make each word first word of line
# by iterating over each index in arr.
for i in range(n - 2, -1, -1):
currlen = -1
dp[i] = sys.maxsize
# Keep on adding words in current
# line by iterating from starting
# word upto last word in arr.
for j in range(i, n):
# Update number of characters
# in current line. arr[j] is
# number of characters in
# current word and 1
# represents space character
# between two words.
currlen += (arr[j] + 1)
# If limit of characters
# is violated then no more
# words can be added to
# current line.
if (currlen > k):
break
# If current word that is
# added to line is last
# word of arr then current
# line is last line. Cost of
# last line is 0. Else cost
# is square of extra spaces
# plus cost of putting line
# breaks in rest of words
# from j+1 to n-1.
if (j == n - 1):
cost = 0
else:
cost = ((k - currlen) *
(k - currlen) + dp[j + 1])
# Check if this arrangement gives
# minimum cost for line starting
# with word arr[i].
if (cost < dp[i]):
dp[i] = cost
ans[i] = j
# Print starting index and ending index
# of words present in each line.
i = 0
while (i < n):
print(i + 1 , ans[i] + 1, end = " ")
i = ans[i] + 1
# Driver Code
if __name__ == "__main__":
arr = [3, 2, 2, 5 ]
n = len(arr)
M = 6
solveWordWrap(arr, n, M)
# This code is contributed by ita_c
C#
// C# program for space
// optimized solution of
// Word Wrap problem.
using System;
class GFG
{
// Function to find space optimized
// solution of Word Wrap problem.
public static void solveWordWrap(int[] arr,
int n, int k)
{
int i, j;
// Variable to store number of
// characters in given line.
int currlen;
// Variable to store possible
// minimum cost of line.
int cost;
// DP table in which dp[i]
// represents cost of line
// starting with word arr[i].
int[] dp = new int[n];
// Array in which ans[i] store
// index of last word in line
// starting with word arr[i].
int[] ans = new int[n];
// If only one word is present
// then only one line is required.
// Cost of last line is zero.
// Hence cost of this line is zero.
// Ending point is also n-1 as
// single word is present.
dp[n - 1] = 0;
ans[n - 1] = n - 1;
// Make each word first
// word of line by iterating
// over each index in arr.
for (i = n - 2; i >= 0; i--)
{
currlen = -1;
dp[i] = int.MaxValue;
// Keep on adding words in
// current line by iterating
// from starting word upto
// last word in arr.
for (j = i; j < n; j++)
{
// Update number of characters
// in current line. arr[j] is
// number of characters in
// current word and 1
// represents space character
// between two words.
currlen += (arr[j] + 1);
// If limit of characters
// is violated then no more
// words can be added to
// current line.
if (currlen > k)
{
break;
}
// If current word that is
// added to line is last
// word of arr then current
// line is last line. Cost of
// last line is 0. Else cost
// is square of extra spaces
// plus cost of putting line
// breaks in rest of words
// from j+1 to n-1.
if (j == n - 1)
{
cost = 0;
}
else
{
cost = (k - currlen) *
(k - currlen) + dp[j + 1];
}
// Check if this arrangement
// gives minimum cost for
// line starting with word
// arr[i].
if (cost < dp[i])
{
dp[i] = cost;
ans[i] = j;
}
}
}
// Print starting index
// and ending index of
// words present in each line.
i = 0;
while (i < n)
{
Console.Write((i + 1) + " " +
(ans[i] + 1) + " ");
i = ans[i] + 1;
}
}
// Driver Code
public static void Main(string[] args)
{
int[] arr = new int[] {3, 2, 2, 5};
int n = arr.Length;
int M = 6;
solveWordWrap(arr, n, M);
}
}
// This code is contributed
// by Shrikant13
PHP
= 0; $i--)
{
$currlen = -1;
$dp[$i] = PHP_INT_MAX;
// Keep on adding words in current
// line by iterating from starting
// word upto last word in arr.
for ($j = $i; $j < $n; $j++)
{
// Update number of characters
// in current line. arr[j] is
// number of characters in
// current word and 1
// represents space character
// between two words.
$currlen += ($arr[$j] + 1);
// If limit of characters
// is violated then no more
// words can be added to
// current line.
if ($currlen > $k)
break;
// If current word that is
// added to line is last
// word of arr then current
// line is last line. Cost of
// last line is 0. Else cost
// is square of extra spaces
// plus cost of putting line
// breaks in rest of words
// from j+1 to n-1.
if ($j == $n - 1)
$cost = 0;
else
$cost = ($k - $currlen) *
($k - $currlen) + $dp[$j + 1];
// Check if this arrangement gives
// minimum cost for line starting
// with word arr[i].
if ($cost < $dp[$i])
{
$dp[$i] = $cost;
$ans[$i] = $j;
}
}
}
// Print starting index and ending index
// of words present in each line.
$i = 0;
while ($i < $n)
{
echo ($i + 1) . " " .
($ans[$i] + 1) . " ";
$i = $ans[$i] + 1;
}
}
// Driver function
$arr = array(3, 2, 2, 5);
$n = sizeof($arr);
$M = 6;
solveWordWrap($arr, $n, $M);
// This code is contributed
// by Akanksha Rai
?>
1 1 2 3 4 4
时间复杂度: O(n ^ 2)
辅助空间: O(n)