自动换行问题(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
相关文章推荐
- 字符串分割单词(word break problem)问题几种解法之比较
- DP19 自动换行问题 Word Wrap Problem @geeksforgeeks
- 常见样式问题七、word-break、word-wrap、white-space区别
- 段落自动换行问题: word-wrap: break-word;
- 最多7次比较解决5个数的排序问题的解法
- 页面对json返回自动result:<pre style="word-wrap: break-word; white-space: pre-wrap;">{"flag":"true"}</pre>问题
- (STL中自带的排序功能7.3.3)POJ 1318 Word Amalgamation(求解一个单词是否在字典里面。解法:将单词按字典序处理后的结果与字典中的单词安字典序处理后的结果进行比较)
- 最优化的几个问题的解法和比较之——无约束的非线性规划
- 段落自动换行问题: word-wrap: break-word;
- TOP-K问题的几种解法
- 最长上升子序列问题的几种解法
- Word Ladder问题及解法
- Unique Substrings in Wraparound String问题及解法
- 标注偏置问题(Label Bias Problem)和HMM、MEMM、CRF模型比较<转>
- 背包问题的几种解法总结
- Maximum Product of Word Lengths 问题及解法
- 最大流问题的几种经典解法综述
- 格子取数问题的动态规划和递归解法之比较
- word-break:break-all和word-wrap:break-word 自动换行问题
- word-wrap:break-word和word-break:break-all的小小比较