题目大意
翻译不好,我来重新解释一下题目。
给定 n n n 个字符串,按字典序从小到大排列。
现在这些排列后的字符串要以一种特殊的规则输出,具体规则如下:
- 我们设每行输出 l l l 个字符串,总共要输出 r r r 行,这 n n n 个字符串中长度最长的字符串长度为 m m m,第 i i i 个字符串的长度为 a i a_i ai。
- 每行 l l l 个字符串中,其中前 l − 1 l-1 l−1 个字符串每个字符串输出后需再输出 m + 2 − a i m+2-a_i m+2−ai 个空格,第 l l l 个字符串输出后需再输出 m − a i m-a_i m−ai 个空格(就是保证每列对齐)。
- 每行最多有 60 60 60 个字符(空格也算字符)。
- 竖向输出,示例如下。
横向输出演示:
123
456
7
竖向输出演示:
147
25
36
思路讲解
首先我们先要求出 l , r l,r l,r。
由于每行最多只有 60 60 60 个字符,所以不难得出:
l = ⌊ 60 − ( a i + m − a i ) a i + m + 2 − a i ⌋ + 1 = ⌊ 60 − m m + 2 ⌋ + 1 l=\lfloor\frac{60-(a_i+m-a_i)}{a_i+m+2-a_i}\rfloor+1=\lfloor\frac{60-m}{m+2}\rfloor+1 l=⌊ai+m+2−ai60−(ai+m−ai)⌋+1=⌊m+260−m⌋+1
求出了 l l l,那么 r r r 也很好求:
r = ⌈ n l ⌉ r=\lceil\frac{n}{l}\rceil r=⌈ln⌉
最难的来了:我们如何竖向输出?
由于 C++ 只允许一行一行地输出,所以我们可以求出在竖向输出中,第 i i i 行,第 j j j 列的字符串,在一维对应着的字符串。
我们设在竖向输出中,第 i i i 行,第 j j j 列的字符串,在一维对应着第 t t t 个字符串,那么就有:
t = ( j − 1 ) × r + i t=(j-1)\times r+i t=(j−1)×r+i
注意若 t > n t>n t>n 时,因跳过此次输出,因为这次输出对应着空缺位置。
其他细节见代码注释。
AC 代码
#include<bits/stdc++.h>
using namespace std;
string a[101];
int main(){
int n,m,l,r,t;
while(cin>>n){//注意这里是认真的多组数据,不是把多组样例分隔开
cout<<"------------------------------------------------------------\n";
m=0;
for(int i=1;i<=n;i++){
cin>>a[i];
m=max(m,(int)a[i].size());//找字符串长度最长的字符串的长度
}
l=(60-m)/(m+2)+1;//求出l
r=ceil(n*1.0/l);//求出r
sort(a+1,a+1+n);//可以直接sort排序
for(int i=1;i<=r;i++){
for(int j=1;j<=l;j++){
t=(j-1)*r+i;//求出在一位数组中对应的字符串
if(t>n){//对应着空缺,跳过
continue;
}
if(j!=l){
cout<<a[t]<<" ";//前l-1个字符串要多输出两个空格
}else{
cout<<a[t];
}
for(int k=1;k<=m-a[t].size();k++){
cout<<' ';//补空格
}
}
cout<<endl;
}
}
return 0;
}