洛谷题解:UVA400 Unix Is命令 Unix ls

题目大意

翻译不好,我来重新解释一下题目。

给定 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 l1 个字符串每个字符串输出后需再输出 m + 2 − a i m+2-a_i m+2ai 个空格,第 l l l 个字符串输出后需再输出 m − a i m-a_i mai 个空格(就是保证每列对齐)。
  • 每行最多有 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+2ai60(ai+mai)+1=m+260m+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=(j1)×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;
}
  • 20
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值