《算法经典》例题5-8Unix Is题解剖析和代码解析(个人笔记)

98 阅读2分钟
  • 在本题中,刘老师所给的代码中少有解释,但是思路很明了。

  • 原题是这样的(Uva原题电子版我没有上网找,直接就拍了紫书的图)

IMG_20230119_190013.jpg

  • 让我们先提取关键字
-   系统输入:正整数n,以及n个文件名(每个文件名由字母与非数字字符组成)  

-   所有文件名经过一次排序  

-   输出格式:按列优先,左对齐(也就是说,是从上到下,从左往右的S形输出);最右列字符宽度为M,其他列的宽度是M+2  
  • 题目读完,我们很容易把第一步的输入搞定。储存文件名的可以是数组,也可以容器vector,这里刘老师用了字符串数组,看起来会简单一些。

string filenames[maxn];

  • for(int i=0;i<n;i++)
  • {
    • cin>>filenames[i];
    • M = max(M,(int)filenames[i].length());
  • }//M的存在是为了在输入一遍的时候就同时计算出了最长文件名的长度,是很经典的一种计算长度的方式,不多做解释。 `
  • 得知了有n个文件名,接下来我们需要根据整数n算出合理的行数列数。可能有部分同学会先设定好行数和列数,但是那样的程序弹性不够好,是草率的方案

无标题.png

  • 像这样根据每一种数据用程序定制出专属的框架,在算法竞赛当中很常见。

  • 那么该怎样去计算行数和列数呢?接下来的代码理解需要一点思考了。刘老师没有对为什么这么计算行数列数做出解释

- int cols = (maxcol-M)/(M+2)+1, rows=(n-1)/cols+1;

  • 这么看是看不出什么端倪的,那么我们用手写的形式把上述表达式写在草稿纸上再看看:

5.png

  • 将表达式移项再变形一下,是不是就清晰一些了呢。我们可以给定最大字符列数maxcol(指的是字符列数,而不是字符串列数,这对于我们利用M来说有帮助),来算出唯一的字符串列数cols,从而再算出唯一的字符串行数rows。这样,“定制”的过程就完成了
    > > 从这个例子我们可以领悟到,在我们阅读他人代码遇到不理解的数学表达式时,可以手写下来,移项变换之后可能就会有突破

  • 继续,排序这部分就不说了,直接调用sort函数即可。输出的关键是通过使用cols,rows来共同决定每一个文件名独一无二的索引idx,这与我们最开始的输入是完美契合的(停下来想想看)。至于什么时候输出前导空格,这点也很容易,不多做解释。输出的部分刘老师用了一个三目运算符和封装函数print,思路清晰的同时也简化了代码。

image.png

image.png