1055 集体照 (25 分)
题目链接
算法分析
本身题目不难理解,但是实现起来比较繁琐。在我的代码里核心的处理思想是
一、用map建立一个链表结构
我们根据题目的要求可知,假设编号1到n的同学身高已经降序排列,那么他们从左往右(输出时的顺序)为:
…
…
8
−
6
−
4
−
2
−
1
−
3
−
5
−
7
−
9
…
…
……8-6-4-2-1-3-5-7-9……
……8−6−4−2−1−3−5−7−9……
因此我们可以初始化这样一个大小为n的链表,然后在每一行输出时,首先求出这一行的学生个数,然后得到不大于这个数的最大偶数,然后从左往右依次处理:1.输出当前同学的名字 2.用链表把位置调到下一个同学的位置。然后直至结束。
二、使用一个“势能”的概念
具体来讲,就是我们每一次获得当前行的学生个数后,虽然我们通过链表得到了对应同学的编号,但是与它在结构体数组中的下标不一致,恰好相差,当前行之前的所有行总共的学生个数。
代码实现
#include<bits/stdc++.h>
using namespace std;
#define N 10005
struct student{
string name;
int height;
}stu[N];
bool cmp(student a, student b){
return a.height == b.height ? a.name < b.name : a.height > b.height;
}
int n, k;
map< int , int >mp;
void init(int m){
if(m % 2 == 1) m -= 1;
int n0 = n;
while(n0 --){
if(m % 2 == 0 && m != 2){
mp[m] = m - 2;
m -= 2;
}
else if(m == 2){
mp[m] = 1;
m -= 1;
}
else{
mp[m] = m + 2;
m += 2;
}
}
return ;
}
void print(int l, int h){
int x = l;
if(l != 1 && l % 2 == 1) x -= 1;
for(int i = 1; i <= l; ++ i){
cout<< stu[x + h].name;
x = mp[x];
if(i < l) printf(" ");
else printf("\n");
}
return ;
}
int main(){
scanf("%d%d", &n, &k);
init(n);
for(int i = 1; i <= n; ++ i)
cin>> stu[i].name>> stu[i].height;
sort(stu + 1, stu + n + 1, cmp);
int h = 0;//势能
for(int i = 1; i <= k; ++ i){
int l = n / k;
if(i == 1) l += n % k;//多出的同学补到最后一排
print(l, h);
h += l;
}
return 0;
}