您的位置:首页 > 编程语言 > Go语言

自动换行问题(word wrap problem )几种解法之比较

2014-04-24 21:59 405 查看

问题描述:

给定一个单词序列和一个每行最做可放多少个字符的限制。需要把这个单词序列按限制行宽摆放完,使得每行剩余的空间的成本和最小。

        在同一行不同单词见的空格符不计入剩余的空间。假定某行的剩余空间是N,则其成本是N*N,举例说明之:

假定给定序列为:"Geeks for Geeks presents word wrap problem", 每行宽度限制为15,

则最优的摆放为:

Geeks for Geeks
presents word
wrap problem

剩余空间的成本之和为: 0 + 2 * 2 + 3 * 3;

具体问题的描述可见(www.geeksforgeeks.org)


问题解法:

下面用三种解法给出答案,分别为

1. 暴力搜索;

2. 递归解法;

3. 动态规划;(注:本文的动态规划解法直接来自geeksforgeeks,笔者目前还没找到更简单的动态规划实现)

1,2仅能给出次优解法,他们的策略为贪婪策略;


解决代码:


#ifndef _WORD_WRAP_H_
#define _WORD_WRAP_H_

#include <stdlib.h>
#include <stdio.h>

/*
* The implementation of the method of brute force search for word wrap problem
*
*/
int WordWrapBrute( const int words[], int size, int width )
{
int len = width;
int cost  = 0;
for( int i = 0; i < size; i++ ) // loop each word
{
if( len  >  words[i] )
{
len -= words[i] + 1;
}
else if( len == words[i] )
{
len -= words[i];
}
else if( len < words[i] )
{
if( len > 0 )
cost += ( len + 1 ) * ( len + 1 );

len = width;
len -= words[i] + 1;
}
}

return cost;
}

/*
* The implementation of recursive method for word wrap problem
*
*/
int WordWrapRecur( const int words[], int size, int cur, int rowIdx, int curWidth, int width )
{
if( cur == size )
{
return 0;
}

for( int i = cur; i < size; i++ )
{
if( curWidth - words[i] >= 0 )
{

return  WordWrapRecur( words, size, i + 1, rowIdx,
curWidth - words[i] - 1, width );
}
else
{
rowIdx++;
if( curWidth != 0 )
{
return ( curWidth + 1) * ( curWidth + 1) +
WordWrapRecur( words, size, i + 1, rowIdx,
width - words[i] - 1, width );
}
else
{
return WordWrapRecur( words, size, i + 1, rowIdx,
width - words[i] - 1, width  );
}
}
}
}

/*
* Output solution when apply to dynamic programming method
*
*/

int OutputSolution( int record[], int size )
{
int k = -1;
if( 1 == record[size] )
{
k = 1;
}
else
{
k = OutputSolution( record, record[size] - 1 ) + 1;
}

printf ("Line number %d: From word no. %d to %d \n", k, record[size], size);
return k;
}

/*
* The implementation of dynamic programming for word wrap problem
*
*/
int WordWrapDP( const int words[], int size, int width )
{

// construct table can be used to record the remainder space when from i to j  in single row
int** table = new int*[size + 1];
assert( table );
for( int i = 0; i <= size; i++ )
{
table[i] = new int[ width + 1 ];
assert( table[i] );
}

// calculate i to j remainder space in single row
for( int i = 1; i <= size; i++ )
{
table[i][i] = width - words[i - 1];
for( int j = i + 1; j <= size; j++ )
{
table[i][j] = table[i][j - 1] - words[j-1] - 1;
}
}

// construct cost array
int** cost = new int*[size + 1];
assert( cost );
for( int i = 0; i <= size; i++ )
{
cost[i] = new int[ width + 1 ];
memset( cost[i], 0x00, sizeof(int)*( width + 1) );
assert( cost[i] );
}

for( int i = 1; i <= size; i++ )
{
for( int j = i; j <= size; j++ )
{
if(  table[i][j] < 0 )
{
cost[i][j] = INT_MAX;
}
else if( size == j && table[i][j] >= 0 )
{
cost[i][j] = 0;
}
else
{
cost[i][j] = table[i][j] * table[i][j];
}

}
}

int* result = new int[size + 1];
int* record = new int[size + 1];
memset( record, 0x00, sizeof(int)*(size + 1) );

result[0] = 0;
for( int j = 1; j <= size; j++ )
{
result[j] = INT_MAX;
for( int i = 1; i <= j; i++ )
{
if( result[i - 1] != INT_MAX && cost[i][j] != INT_MAX &&
result[i - 1] + table[i][j] < result[j] )
{
result[j] = result[i - 1] + table[i][j];
record[j] = i;
}
}
}

OutputSolution( record, size );

for( int i = 0; i <= size; i++ )
{
delete [] table[i];
delete [] cost[i];
}

delete [] table;
delete [] cost;

return 0;
}

void TestWordWrap()
{
int words[] = {3, 2, 2, 5};
int size = sizeof(words)/sizeof(words[0]);
int width =  6;

int cost = WordWrapRecur( words, size, 0, 1, 6, 6 );
int newCost = WordWrapBrute( words, size, width );

WordWrapDP( words, size, width );
getchar();

}

#endif





                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息