问题描述
在absi2011的帮派里,死号偏多。现在absi2011和帮主等人联合决定,要清除一些死号,加进一些新号,同时还要鼓励帮贡多的人,对帮派进行一番休整。
目前帮派内共最多有一位帮主,两位副帮主,两位护法,四位长老,七位堂主,二十五名精英,帮众若干。
现在absi2011要对帮派内几乎所有人的职位全部调整一番。他发现这是个很难的事情。于是要求你帮他调整。
他给你每个人的以下数据:
他的名字(长度不会超过30),他的原来职位,他的帮贡,他的等级。
他要给帮贡最多的护法的职位,其次长老,以此类推。
可是,乐斗的显示并不按帮贡排序而按职位和等级排序。
他要你求出最后乐斗显示的列表(在他调整过职位后):职位第一关键字,等级第二关键字。
注意:absi2011无权调整帮主、副帮主的职位,包括他自己的(这不是废话么…)
他按原来的顺序给你(所以,等级相同的,原来靠前的现在也要靠前,因为经验高低的原因,但此处为了简单点省去经验。)
输入格式
第一行一个数n,表示星月家园内帮友的人数。下面n行每行两个字符串两个整数,
表示每个人的名字、职位、帮贡、等级。
输出格式
一共输出n行,每行包括排序后乐斗显示的名字、职位、等级。
输入输出样例
输入 #1
9
DrangonflyKang BangZhu 100000 66
RenZaiJiangHu FuBangZhu 80000 60
absi2011 FuBangZhu 90000 60
BingQiLingDeYanLei HuFa 89000 58
Lcey HuFa 30000 49
BangYou3 ZhangLao 1000 1
BangYou1 TangZhu 100 40
BangYou2 JingYing 40000 10
BangYou4 BangZhong 400 1
输出 #1
DrangonflyKang BangZhu 66
RenZaiJiangHu FuBangZhu 60
absi2011 FuBangZhu 60
BingQiLingDeYanLei HuFa 58
BangYou2 HuFa 10
Lcey ZhangLao 49
BangYou1 ZhangLao 40
BangYou3 ZhangLao 1
BangYou4 ZhangLao 1
说明/提示
各种职位用汉语拼音代替。
如果职位剩1个,而有2个帮贡相同的人,则选择原来在前的现在当选此职位。
【数据范围】
对于10%的数据,保证n=3
对于40%的数据,保证各个人的帮贡均为0
对于100%的数据,保证3<=n<=110,各个名字长度<=30,0<=各个人的帮贡<=1000000000
1<=各个人等级<=150
保证职位必定为BangZhu,FuBangZhu,HuFa,ZhangLao,TangZhu,JingYing,BangZhong之间一个
保证有一名帮主,保证有两名副帮主,保证有一名副帮主叫absi2011
不保证一开始帮派里所有职位都是满人的,但排序后分配职务请先分配高级职位。例如原来设一名护法现在设两名。
保证名字不重复。
问题分析
这是一道经典的模拟和排序题,按照题目所描述,因为帮主和副帮主我们不能进行改变,所以我们要先把帮主和副帮主找出来与前三个成员的位置进行互换,然后再对剩下的n-3个帮派成员的帮贡进行排序,如果帮贡相同则按原来给定的顺序进行排序。完成上述操作后,再按照顺序依次给众人赋予护法,长老,堂主,精英,帮众的职位。然后再对所有的成员进行职位排序、若职位相同则进行等级排序,若等级又相同则按照原有的顺序排序,最后便能够得出正确的排序结果。
ps:因为sort排序是不稳定的,所以并不一定会让相同值的排序满足原有顺序,所以需要进行额外的顺序排序
代码实现
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
struct ledou
{
string n; //名字
string z; //职位
long long g; //帮贡
int l; //等级
int k; //原有顺序
};
void Input(int n, ledou s[]);
void Output(int n, ledou s[]);
void Sort(int n, ledou s[]);
int Switch(string str);
bool cmp(const ledou& s1, const ledou& s2);
bool cmp2(const ledou& s1, const ledou& s2);
int main()
{
ledou s[200];
int n;
cin >> n;
Input(n, s);
Sort(n,s);
Output(n, s);
return 0;
}
void Input(int n, ledou s[])
{
for (int i = 0; n > i; i++)
{
cin >> s[i].n >> s[i].z >> s[i].g >> s[i].l;
s[i].k = i;
}
}
void Output(int n, ledou s[])
{
for (int i = 0; n > i; i++)
cout << s[i].n << ' ' << s[i].z << ' ' << s[i].l << endl;
}
void Sort(int n, ledou s[])
{
int t = 1;
ledou temp;
for (int i = 0; n > i; i++) //将帮主和副帮主与前三位成员互换位置
{
if (s[i].z == "BangZhu")
{
temp = s[i];
s[0] = s[i];
s[i] = temp;
}
if (s[i].z == "FuBangZhu")
{
temp = s[t];
s[t] = s[i];
s[i] = temp;
t++;
}
}
sort(s + 3, s + n, cmp); //按照帮贡排序
for (int i = 0; n > i; i++) //赋予职位
{
if (s[i].z != "BangZhu" && s[i].z != "FuBangZhu")
{
if (t < 5)
s[t++].z = "HuFa";
if (t >= 5 && t < 9)
s[t++].z = "ZhangLao";
if (t >= 9 && t < 16)
s[t++].z = "TangZhu";
if (t >= 16 && t < 41)
s[t++].z = "JingYing";
if (t >= 41)
s[t++].z = "BangZhong";
}
}
sort(s, s + n, cmp2); //按照职位、等级和原有顺序进行排序
}
bool cmp(const ledou &s1,const ledou &s2)
{
if (s1.g != s2.g)
return s1.g > s2.g;
else
return s1.k < s2.k;
}
bool cmp2(const ledou &s1,const ledou &s2)
{
int a = Switch(s1.z);
int b = Switch(s2.z);
if (a != b)
return a < b;
else
if (s1.l != s2.l)
return s1.l > s2.l;
else
return s1.k < s2.k;
}
int Switch(string str) //为了方便职位之间的比较,将职位量化
{
if (str == "BangZhu") return 1;
if (str == "FuBangZhu") return 2;
if (str == "HuFa") return 3;
if (str == "ZhangLao") return 4;
if (str == "TangZhu") return 5;
if (str == "JingYing") return 6;
if (str == "BangZhong") return 7;
}
运行结果
总结
这是一道典型的模拟+排序题目,主要考察对模拟和排序的熟悉程度,之前因为不知道sort排序是不稳定的排序而始终得不出正确的排序序列,需要引起注意,整体难度一般。