码迷,mamicode.com
首页 > 编程语言 > 详细

PAT 乙级 1055.集体照 C++/Java

时间:2020-01-25 18:12:05      阅读:90      评论:0      收藏:0      [点我收藏+]

标签:遍历   意思   https   输入   ace   长度   iostream   执行   开始   

题目来源

拍集体照时队形很重要,这里对给定的 N 个人 K 排的队形设计排队规则如下:

  • 每排人数为 /(向下取整),多出来的人全部站在最后一排;

  • 后排所有人的个子都不比前排任何人矮;

  • 每排中最高者站中间(中间位置为 /,其中 m 为该排人数,除法向下取整);

  • 每排其他人以中间人为轴,按身高非增序,先右后左交替入队站在中间人的两侧(例如5人身高为190、188、186、175、170,则队形为175、188、190、186、170。这里假设你面对拍照者,所以你的左边是中间人的右边);

  • 若多人身高相同,则按名字的字典序升序排列。这里保证无重名。

现给定一组拍照人,请编写程序输出他们的队形。

输入格式:

每个输入包含 1 个测试用例。每个测试用例第 1 行给出两个正整数 N(≤,总人数)和 K(≤,总排数)。随后 N 行,每行给出一个人的名字(不包含空格、长度不超过 8 个英文字母)和身高([30, 300] 区间内的整数)。

输出格式:

输出拍照的队形。即K排人名,其间以空格分隔,行末不得有多余空格。注意:假设你面对拍照者,后排的人输出在上方,前排输出在下方。

输入样例:

10 3
Tom 188
Mike 170
Eva 168
Tim 160
Joe 190
Ann 168
Bob 175
Nick 186
Amy 160
John 159
 

输出样例:

Bob Tom Joe Nick
Ann Mike Eva
Tim Amy John

分析:

第三排:Bob Tom Joe Nick
第二排:Ann Mike Eva
第一排:Tim Amy John

单独看第三排的人的身高
Bob Tom  Joe  Nick
175 188  190  186

假定最开始他们是有序的
即:190 188 186 175
题目要求的是,最高的在中间,按身高非增序,先右后左交替入队站在中间人的两侧(这里的左右,是相对于中间人的左右,即。我们面对着中间人,对我们来说就是先左后右
什么意思呢?
首先,我们先把最高的放中间,190
接着,先左后右的入队,下一个 188,变成 188 190
然后,186 入队, 变成 188 190 186
以此类推可以得到:175 188 190 186
稍微分析一下可以发现这个身高排名规律:
175 188 190 186
no4 no2 no1 no3
(就类似领奖台的那种,冠亚季军站旁边)


假定条件:
t - 用来记录当前一排的最大值的下标,初始化为0
m - 当前一排的人数
res - 存放当前一排的人的名字
peoples - 所有人的名字、身高(已排序,高到低)

1. 首先:
 res[m/2] = 身高最高的; // res[m/2] = 190 

2. 遍历 188 186 175,将 188 和 175 放在 190 的左边
int j = 0;
for (int i = t + 1; i < m + t; i += 2) {
    res[j++] = peoples[i].name;
}

 i += 2 就是隔一个取一个

 m + t 就可以理解为是一个范围,每次循环,输出peoples数组 [ t, m + t)的内容(看后面解析)

 i = t + 1 此时 t = 0,即从 peoples[1]开始,隔一个取一个(peoples[0]已经放到了中间)

第一行是 m = 4, t = 0, 那么这一排的人在peoples中的下标就是 [ 0 , 3)

 res 数组变成了 188 175 190

3. 这时候发现,我们要的是 175 188 190,怎么办呢?reverse翻转
 reverse(res.begin(), res.begin() + j); 

4. 接着我们来处理 190 的右边,和第二步是一样的做法,需要注意的是,执行完第二部之后,另 j += 1 ,因为此时 j == m/2
 for (int i = t + 2; i < m + t; i += 2) { res[j++] = peoples[i].name; } 
 
  这种情况就不用 reverse 了,因为是按高到低的顺序放到右边的
5. 输出当前一排(没啥好说的了,注意格式
6. 更新 row 和 t 的值
   row--; 
   t = m + t 
  理解一下 t = m + t

怎么理解 t = m + t 

  1. 当 m = 4, t = 0 时:输出的是  peoples[0] ~ peoples[3] ,更新 t = m + t = 4 + 0 = 4;
  2. 当 m = 3, t = 4 时:输出的是  peoples[4] ~ peoples[6] ,更新 t = m + t = 3 + 4 = 7;
  3. 当 m = 3, t = 7 时:输出的是  peoples[7] ~ peoples[9] .....

C++实现:

#include <iostream>
#include <string>
#include<algorithm>
#include <stack>
#include <queue>
#include <unordered_map>
#include <iomanip>
using namespace std;

/*
190、188、186、175、170

-> 175、188、190、186、170
-> no4、no2、no1、no3、no5
*/ typedef struct Person { string name; int height; }Person; bool cmp(Person a, Person b) { if (a.height != b.height) { return a.height > b.height; } else { return a.name < b.name; } } int main() { int K; // 总排数 int N; // 总人数 cin >> N >> K; vector<Person> peoples(N); for (int i = 0; i < N; ++i) { cin >> peoples[i].name >> peoples[i].height; } sort(peoples.begin(), peoples.end(), cmp); int t = 0; int row = K; // 当前是第几排 int m = 0; // 当前一排的人数 while (row) { if (row == K) { m = N - (K - 1)* N / K; // N÷K是每排的人数 } else { m = N / K; } // 数组都排好序了 // 190, 188, 186, 175, 170, 168, 168, 160, 160, 159 // N = 10, K = 3 // row = 3 // m = N - (K - 1)* N / K // = 10 - (3 - 1) * 10 / 3 // = 10 - 2 * 3 // = 4 最后一排有4个人 vector<string> res(m); //保存目前一排的人的名字 // t = 0, peoples[0]是最大的190,把它放到中间,也就是m/2 res[m / 2] = peoples[t].name; // 接着把188,175放到res[m/2]的左边(保持顺序175 188 res[m/2]),即:隔一个就取一个放到左边 int j = 0; for (int i = t + 1; i < m + t; i += 2) { res[j++] = peoples[i].name; } reverse(res.begin(), res.begin() + j); // 把186,放到res[m/2]的右边(保持顺序),即:隔一个就取一个放到右边 j += 1; for (int i = t + 2; i < m + t; i += 2) { res[j++] = peoples[i].name; } // 输出 cout << res[0]; for (int i = 1; i < m; ++i) { cout << << res[i]; } cout << endl; t = t + m; row--; } return 0; }

 

 

Java实现:

 

PAT 乙级 1055.集体照 C++/Java

标签:遍历   意思   https   输入   ace   长度   iostream   执行   开始   

原文地址:https://www.cnblogs.com/47Pineapple/p/12233231.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!