1055 集体照 C++

在这里插入图片描述
思路分析:
这道题乍一看挺麻烦的,其实则不然。本题主要难点是以下两步:
1.首先需要将所有人按给定的排序规则存储到容器中,这就需要用到容器的自定义排序。
2.”每排其他人以中间人为轴,按身高非增序,先右后左交替入队站在中间人的两侧” 这句话看似很复杂,其实只需要用双端队列就可以解决,当然也可以找到数字之间的规律。

具体步骤:

  1. 声明结构体或类,取名为Person,内部维护name、height两个成员变量,权限为public;
  2. 自定义排序规则MySort,按照题目指定规则排序;
  3. 在主函数中读取待排队人员并进行排列供后面使用;
  4. 判断能否正好排成矩阵,并记录最多排成矩阵的列数为k2;
  5. 执行k2次循环,每个循环内选中一排进行双端交替入队,用一个标记位判断是从队头进还是队尾进,当一排全部入队之后,将整一排信息入栈;
  6. 如果不能排成矩阵,说明还有剩余的人,而且一定是高个。与步骤5同样的道理排队并入栈;
  7. 依次将栈中元素出栈,就得到了所求结果。

示例代码:

#include<iostream>
#include<vector>
#include<string>
#include<deque>
#include<stack>
#include<algorithm>
using namespace std;
class Person {
public:
    string name;
    int height;
};
struct MySort{
public:
	bool operator()(const Person& p1, const Person p2){
		if(p1.height < p2.height){
			return true;
		}else if(p1.height == p2.height && p1.name > p2.name){
			return true;
		}
		return false;
	}
};
int main(){
	int n,k; cin >> n >> k;
	vector<Person> vec;
	for(int i = 0; i < n; i++){
		string str;int wei;
		cin>>str>>wei;
		Person p;
		p.name = str;
		p.height = wei;
		vec.push_back(p);
	}
	sort(vec.begin(),vec.end(),MySort());//把人员升序排列
	stack<deque<Person>> sta;//存储所有排队讯息
	int num = n/k;//向下取整 每队队列人数
	int k2 = k;
	if(num * k != n){//不能排成k队
		k2 = k-1;
	}
	int point = 0;//记录每一排的起始角标
	for(int i = 0; i < k2; i++){//执行k2次 保证不会溢出
		bool front = false;//判断当前是进队头还是队尾
		deque<Person> de;//用来存储每一队的信息
		for(int j = point+num-1; j >= point; j--){//执行k2次,总共选中一队的人
			if(front){
				de.push_front(vec[j]);
				front = false;
			}else{
				de.push_back(vec[j]);
				front = true;
			}
		}
		sta.push(de);
		point += num;//移到下一排的队头
	}
	if(k2 != k){//说明还有余下的高个
		deque<Person> de;//用来存储每一队的信息
		bool front = false;
		for(int i = vec.size() - 1; i >= point; i--){
			if(front){
				de.push_front(vec[i]);
				front = false;
			}else{
				de.push_back(vec[i]);
				front = true;
			}
		}
		sta.push(de);
	}
	while(!sta.empty()){//将栈中的队列逆序输出
		deque<Person> de = sta.top();
		for(deque<Person>::iterator it = de.begin(); it != de.end()-1; it++){
			cout << (*it).name <<" ";
		}
		cout<<(*(de.end()-1)).name<<endl;
		sta.pop();
	}
	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值