紫书刷题进行中,题解系列【GitHub|CSDN】
例题5-8 UVA400 Unix ls(28行AC代码)
题目大意
给若干文件名,按字典序排列后,按列输出。其中每行60个字符,假设文件名最长长度为len,最后一列所占宽度为len,其余列占宽度为len+2,要求行数尽可能少。
思路分析
使用set<string>_set
可自动按字典序排列
本题关键在于计算输出的行列数,假设文件名中最长长度为len,n为列数,那么总行列宽计算公式如下:
总列宽=(len+2)*(n-1)+len=(len+2)*n-2
行宽= ceil(n/列宽) // 向上取整
- 可用
%-len
来控制输出对齐格式
注意点
- 最后一列对齐宽度为最大长度,其余列需+2
- 左对齐,按列输出
AC代码(C++11,按列输出,行列计算)
#include<bits/stdc++.h>
using namespace std;
int n;
string s, format;
int main() {
while (cin >>n) {
int maxlen=-1, len, colNum=1, rowNum;
set<string> _set;
for (int i = 0; i < n; i ++) {
cin >>s; _set.insert(s);
maxlen = max(maxlen, (int)s.size()); // 最长长度
}
while ((maxlen+2)*colNum-2 <= 60) colNum++; // 列数
colNum --; rowNum = (int)ceil((float)n / colNum); // 行数
vector<string> fnames;
fnames.insert(fnames.begin(), _set.begin(), _set.end()); // set转为vector
printf("%s\n", string(60,'-').c_str()); // 60个-
for (int i = 0; i < rowNum; i ++) { // 遍历输出
for (int j = 0; j < colNum && j*rowNum+i < n; j ++) {
len = (j == colNum-1) ? maxlen : maxlen+2; // 最后一列对其宽度为maxlen
format = "%-"+to_string(len)+"s"; // 输出格式
printf(format.c_str(), fnames[j*rowNum+i].c_str());
}
puts("");
}
}
return 0;
}