题目的难点在于要求前面的每一列的是最大长度L+2,最后一列的长度是L。对于宽度为WIDTH=60的一行来说,一行可以放下多少个单词决定了需要多少行,知道了行数才能开始根据行数开始放置。
我的做法是col = (WIDTH+ 2) / (L + 2)
,即提前给WIDTH
加2,这个是给最后一列加的,因为实际上最后一列会减去这个2,所以加2没有影响。
看了一下书中的做法,是col = (WIDTH - L) / (L + 2) + 1
,即先把最后一列减去,因为L <= WIDTH
,所以可以保证col
大于0,效果相同。
然后对于第i
行第j
列,我们要判断在实际排好序的单词数组中的位置,最后一行还需要判断是否已经结束(因为最后一行有可能没有满)
书中是自己写了一个控制输出流的,我用的是C++自己的流控制,需要iomanip
头文件,然后使用操纵符setw
设置最小宽度,使用left
控制左对齐(默认是右对齐)
需要注意algorithm
库中的max
函数的两个参数必须类型相同
#include <iostream>
#include <string>
#include <array>
#include <algorithm>
#include <sstream>
#include <iomanip>using namespace std;namespace {constexpr int MAXN = 105;constexpr int WIDTH = 60;array<string, MAXN> words;const string LINE(WIDTH, '-');int n;size_t max_len, word_len;int row, col, n_idx, idx;
}int main() {ios::sync_with_stdio(false);while (cin >> n) {ostringstream os;os << left;max_len = 0;for (int i = 0; i < n; ++i) {cin >> words[i];max_len = max(max_len, words[i].size());}sort(words.begin(), words.begin() + n);col = (WIDTH + 2) / (max_len + 2);row = (n - 1) / col + 1;for (int i = 0; i < row; ++i) {for (int j = 0; j < col; ++j) {idx = j * row + i;n_idx = (j + 1) * row + i;if (n_idx >= n) {word_len = max_len;} else {word_len = max_len + 2;}os << setw(word_len) << words[idx];if (word_len == max_len) {os << "\n";break;}}}cout << LINE << "\n";cout << os.str();}return 0;
}