异想之旅:本人原创博客完全手敲,绝对非搬运,全网不可能有重复;本人无团队,仅为技术爱好者进行分享,所有内容不牵扯广告。本人所有文章仅在CSDN、掘金和个人博客(一定是异想之旅域名)发布,除此之外全部是盗文!
题目背景
在absi2011的帮派里,死号偏多。现在absi2011和帮主等人联合决定,要清除一些死号,加进一些新号,同时还要鼓励帮贡多的人,对帮派进行一番休整。
题目描述
目前帮派内共最多有一位帮主,两位副帮主,两位护法,四位长老,七位堂主,二十五名精英,帮众若干。
现在absi2011要对帮派内几乎所有人的职位全部调整一番。他发现这是个很难的事情。于是要求你帮他调整。
他给你每个人的以下数据:
他的名字(长度不会超过30),他的原来职位,他的帮贡,他的等级。
他要给帮贡最多的护法的职位,其次长老,以此类推。
可是,乐斗的显示并不按帮贡排序而按职位和等级排序。
他要你求出最后乐斗显示的列表(在他调整过职位后):职位第一关键字,等级第二关键字。
注意:absi2011无权调整帮主、副帮主的职位,包括他自己的(这不是废话么…)
他按原来的顺序给你(所以,等级相同的,原来靠前的现在也要靠前,因为经验高低的原因,但此处为了简单点省去经验。)
输入格式
第一行一个数n,表示星月家园内帮友的人数。
下面n行每行两个字符串两个整数,表示每个人的名字、职位、帮贡、等级。
输出格式
一共输出n行,每行包括排序后乐斗显示的名字、职位、等级。
输入输出样例
In 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
Out 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
标题提到的细思极恐等会再说。
这道题就是一个残害竞赛生的排序啊……
首先存储每个成员的结构体如下
struct node {
string name, zw; // 名字,当前职位
long long bg, dj, id; // 帮贡,等级,输入顺序
} a[200], fbz[2]; // a存正常成员,fbz存储副帮主
首先帮主和副帮主不参与调整,所以对于帮主读取到之后可以直接输出,而副帮主两个输入之后比较一下谁的等级高先输出谁就行了(虽然这道题在这里数据不强,不比较副帮主也是可以ac的,洛谷题解里很多都没考虑副帮主的问题,甚至有直接读入前三行输出的)
所以在这里设计输入如下
long long n;
cin >> n;
for (long long i = 0; i < n; i++) {
cin >> a[i].name >> a[i].zw >> a[i].bg >> a[i].dj;
a[i].id = i; // 输入的顺序,方便过后排序
if (a[i].zw == "BangZhu") {
// 帮主直接输出
cout << a[i].name << " " << a[i].zw << " " << a[i].dj << endl;
// 帮主不存进a里面,所以i和n要--(下面副帮主同)
i--;
n--;
} else if (a[i].zw == "FuBangZhu") {
// 副帮主先存进fbz数组,要比较两个副帮主的等级之后再输出
fbz[fbzl++] = a[i];
i--;
n--;
}
}
if (fbz[0].dj < fbz[1].dj) swap(fbz[0], fbz[1]); // 看当前两个副帮主顺序是否正确
for (int i = 0; i < 2; i++)
cout << fbz[i].name << " " << fbz[i].zw << " " << fbz[i].dj << endl; // 完成副帮主输出
至此完成了数据输入和帮主、副帮主的处理。
除此三人之外的其他人按照帮贡第一关键字、输入顺序第二关键字排序,可以直接结构体+cmp函数+sort实现(虽然按帮贡排序后通常情况相同帮贡会保持先输入的在前面,但是为了保险还是进行双关键字吧)
对结构体进行排序的cmp函数如下
bool cmp(node x, node y) {
if (x.bg != y.bg)
return x.bg > y.bg; // 帮贡不同帮贡大的在前
else
return x.id < y.id; // 否则排输入顺序
}
很多人说不会cmp函数到底怎么设计,这里给大家一个很简单的理解:cmp函数的参数x和y,如果x在前y在后是正确的return 1,否则return 0,简单说就是问x在前y在后这个顺序对不对
具体可以看这篇文章 干货:详解C++ sort函数的cmp参数!_异想之旅的博客-CSDN博客 (如果帮到了你还不赶快三连!)
然后就是一个咋看咋好用的sort了
sort(a, a + n, cmp);
往下我这个方法不是最好的,也很有可能是这里的书写才导致了那个细思极恐的问题,但是作为结构体和sort的练习等还是不错的
我们再开一个结构体存储帮主和副帮主之外的职位:
struct Node {
string name;
long long cnt;
} zw[10]; // zw就是职位
然后在main函数开头写上这一段
zw[0].name = "HuFa";
zw[0].cnt = 2;
zw[1].name = "ZhangLao";
zw[1].cnt = 4;
zw[2].name = "TangZhu";
zw[2].cnt = 7;
zw[3].name = "JingYing";
zw[3].cnt = 25;
zw[4].name = "BangZhong";
zw[4].cnt = 100000000;
众所周知,sort函数可以排数组的片段
所以我们首先为相同职位的再写一个cmpp函数
bool cmpp(node x, node y) {
if (x.dj != y.dj)
return x.dj > y.dj;
else
return x.id < y.id;
}
和上面的cmp类似,不再赘述,就是要注意因为等级相同还是按照输入顺序,所以不要忘了id的比较
最终的排序和输出,看注释
long long l = 0, i;
for (i = 0; i < 4; i++) { // 完成除帮众外的排序和输出
if (n - l >= zw[i].cnt) {
// 分析可知从数组索引l(含)到索引l + zw[i].cnt(不含)是当前职位的所有人
sort(a + l, a + l + zw[i].cnt, cmpp); // 按照等级和输入顺序排序
for (long long j = l; j < l + zw[i].cnt; j++)
cout << a[j].name << " " << zw[i].name << " " << a[j].dj << endl; // 输出
l += zw[i].cnt; // 左指针自增,在此之前的都处理完了
} else
break; // 如果人数不足以分配完当前职位了就跳出
}
if (n - l > 0) { // 还有没分配的人
sort(a + l, a + n, cmpp); // 排序剩下的没分配的所有人
for (long long j = l; j < n; j++)
cout << a[j].name << " " << zw[i].name << " " << a[j].dj << endl;
}
这个程序在对于帮众的处理是没有bug的,自己尝试理解一下,实在不懂评论区提问我会解答
然后就附上完整的ac代码吧(我知道你就是奔着这里点开这篇文章的不是吗)
#include <bits/stdc++.h>
using namespace std;
struct node {
string name, zw;
long long bg, dj, id;
} a[200], fbz[2];
struct Node {
string name;
long long cnt;
} zw[10];
long long fbzl = 0;
bool cmp(node x, node y) {
if (x.bg != y.bg)
return x.bg > y.bg;
else
return x.id < y.id;
}
bool cmpp(node x, node y) {
if (x.dj != y.dj)
return x.dj > y.dj;
else
return x.id < y.id;
}
int main() {
zw[0].name = "HuFa";
zw[0].cnt = 2;
zw[1].name = "ZhangLao";
zw[1].cnt = 4;
zw[2].name = "TangZhu";
zw[2].cnt = 7;
zw[3].name = "JingYing";
zw[3].cnt = 25;
zw[4].name = "BangZhong";
zw[4].cnt = 100000000;
long long n;
cin >> n;
for (long long i = 0; i < n; i++) {
cin >> a[i].name >> a[i].zw >> a[i].bg >> a[i].dj;
a[i].id = i;
if (a[i].zw == "BangZhu") {
cout << a[i].name << " " << a[i].zw << " " << a[i].dj << endl;
i--;
n--;
} else if (a[i].zw == "FuBangZhu") {
fbz[fbzl++] = a[i];
i--;
n--;
}
}
if (fbz[0].dj < fbz[1].dj) swap(fbz[0], fbz[1]);
for (int i = 0; i < 2; i++)
cout << fbz[i].name << " " << fbz[i].zw << " " << fbz[i].dj << endl;
sort(a, a + n, cmp);
long long l = 0, i;
for (i = 0; i < 4; i++) {
if (n - l >= zw[i].cnt) {
// cout << i << zw[i].name << zw[i].cnt << endl;
sort(a + l, a + l + zw[i].cnt, cmpp);
for (long long j = l; j < l + zw[i].cnt; j++)
cout << a[j].name << " " << zw[i].name << " " << a[j].dj
<< endl;
l += zw[i].cnt;
} else
break;
}
if (n - l > 0) {
sort(a + l, a + n, cmpp);
for (long long j = l; j < n; j++)
cout << a[j].name << " " << zw[i].name << " " << a[j].dj << endl;
}
return 0;
}
细思极恐的就是
在我调试程序时
第76行输出的两个i居然不一样!
而且访问不到zw数组中的cnt!
并且似乎不是所有电脑都出现这样的表现(xth同学试了似乎没问题?)
代码放这里了
高人请指点,必有重谢!!!!
/*输入数据
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
*/
#include <bits/stdc++.h>
using namespace std;
struct node {
string name, zw;
long long bg, dj, id;
} a[200], fbz[2];
struct Node {
string name;
long long cnt;
} zw[10];
long long fbzl = 0;
bool cmp(node x, node y) {
if (x.bg != y.bg)
return x.bg > y.bg;
else
return x.id < y.id;
}
bool cmpp(node x, node y) {
if (x.dj != y.dj)
return x.dj > y.dj;
else
return x.id < y.id;
}
int main() {
// freopen("D:/Desktop/11.txt", "r", stdin);
// freopen("D:/Desktop/1.txt", "w", stdout);
zw[0].name = "HuFa";
zw[0].cnt = 2;
zw[1].name = "ZhangLao";
zw[1].cnt = 4;
zw[2].name = "TangZhu";
zw[2].cnt = 7;
zw[3].name = "JingYing";
zw[3].cnt = 25;
zw[4].name = "BangZhong";
zw[4].cnt = 100000000;
long long n;
cin >> n;
for (long long i = 0; i < n; i++) {
cin >> a[i].name >> a[i].zw >> a[i].bg >> a[i].dj;
a[i].id = i;
if (a[i].zw == "BangZhu") {
cout << a[i].name << " " << a[i].zw << " " << a[i].dj << endl;
i--;
n--;
} else if (a[i].zw == "FuBangZhu") {
fbz[fbzl++] = a[i];
i--;
n--;
}
}
if (fbz[0].dj < fbz[1].dj) swap(fbz[0], fbz[1]);
for (int i = 0; i < 2; i++)
cout << fbz[i].name << " " << fbz[i].zw << " " << fbz[i].dj << endl;
// cout << endl;
sort(a, a + n, cmp);
for (int i = 0; i < n; i++) cout << a[i].id << " ";
cout << endl << n << endl;
long long l = 0, i;
for (i = 0; i < 3; i++) {
cout << i << " ";
if (n - l >= zw[i].cnt) {
cout << i << " ";
sort(a + l, a + l + zw[i].cnt, cmpp);
cout << i << "\n";
printf("%ld ", i);
printf("i:%ld %ld %ld i:%ld cnt:%ld\n", i, l, (l + zw[i].cnt), i,
zw[i].cnt);
// for (long long j = l; j < l + zw[i].cnt; j++)
// cout << a[j].id << " " << a[j].name << " " << zw[i].name << "
// "
// << a[j].dj << endl;
// printf("%ld %ld i:%ld cnt:%ld\n", l, (l + zw[i].cnt), i,
// zw[i].cnt);
l += zw[i].cnt;
} else
break;
}
// if (n - l > 0) {
// sort(a + l, a + n, cmpp);
// for (long long j = l; j < n; j++)
// cout << a[j].id << " " << a[j].name << " " << zw[i].name << " "
// << a[j].dj << endl;
// }
return 0;
}
(少年,这个可不是ac代码,去掉调试也只有30分而已,你要抄的在前面!)