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

来源:互联网 发布:电话数据统计 编辑:程序博客网 时间:2024/06/07 07:59

问题描述:

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

        在同一行不同单词见的空格符不计入剩余的空间。假定某行的剩余空间是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 rowint** 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 rowfor( 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 arrayint** 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 


      


0 0
原创粉丝点击