排序
A1062
本题关键是如何分类和写cmp函数。在结构体里增加flag表示为每个学生的等级。在读入的数据的时候对数据进行分类即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 100010;
struct Person
{
int de, cai, sum;
int id;
int flag;
}stu[N];
bool cmp(Person a, Person b)
{
if(a.flag != b.flag) return a.flag < b.flag;
else if(a.sum != b.sum) return a.sum > b.sum;
else if(a.de != b.de) return a.de > b.de;
else return a.id < b.id;
}
int main()
{
int n, high, low;
scanf("%d%d%d", &n, &low, &high);
int num = n;
for(int i = 0; i < n; i++)
{
scanf("%d %d %d", &stu[i].id, &stu[i].de, &stu[i].cai);
stu[i].sum = stu[i].de + stu[i].cai;
if(stu[i].de < low || stu[i].cai < low)
{
stu[i].flag = 5;
num --;
}
else
{
if(stu[i].de >= high && stu[i].cai >= high)
stu[i].flag = 1;
else if(stu[i].de >= high && stu[i].cai < high)
stu[i].flag = 2;
else if(stu[i].de >= stu[i].cai)
stu[i].flag = 3;
else
stu[i].flag = 4;
}
}
sort(stu, stu + n, cmp);
printf("%d\n", num);
for(int i = 0; i < num; i++)
{
printf("%d %d %d\n",stu[i].id, stu[i].de, stu[i].cai);
}
return 0;
}
A1012
本题需要建立一个二维数组来存储每个学生的rank排名,同时需要将学生的id用int存储,这样rank[id][now]就可以直接得出学生的具体科目的成绩,同时需要比较不同科目的时候可以在bool函数设置一个全局变量,在函数里改变全局变量就可以排序不同的内容。需要注意如何四舍五入。在读入所有的数据后进行排序,因为有四个学科所以得出可以四次外循环,外循环内进行排序,在内循环内进行rank的更新。输出时可以建立字符数组用来int和char的映射,因为优先级是A>C>M>E。所以字符数组也为这个顺序并从a开始遍历寻找找好排名。
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
struct student
{
int id;
int grade[4];
}stu[2010];
char course[4] = {'A', 'C', 'M', 'E'};
int Rank[10000000][4] = {0};
int now;
bool cmp(student a, student b)
{
return a.grade[now] > b.grade[now];
}
int main()
{
int n, m;
scanf("%d %d", &n, &m);
for(int i = 0; i < n; i++)
{
scanf("%d%d%d%d", &stu[i].id, &stu[i].grade[1], &stu[i].grade[2], &stu[i].grade[3]);
stu[i].grade[0] = round((stu[i].grade[1] + stu[i].grade[2] + stu[i].grade[3]) / 3.0);
// printf("%d %d %d %d %d\n",stu[i].id, stu[i].grade[0], stu[i].grade[1], stu[i].grade[2], stu[i].grade[3]);
}
for(now = 0; now < 4; now ++)
{
sort(stu, stu + n, cmp);
Rank[stu[0].id][now] = 1;
for(int j = 1; j < n; j++)
{
if(stu[j].grade[now] == stu[j - 1].grade[now])
Rank[stu[j].id][now] = Rank[stu[j - 1].id][now];
else
Rank[stu[j].id][now] = j + 1;
}
}
int query;
for(int i = 0; i < m; i++)
{
scanf("%d", &query);
if(Rank[query][0] == 0)
printf("N/A\n");
else
{
int k = 0;
for(int j = 1; j < 4; j++)
{
if(Rank[query][j] < Rank[query][k])
k = j;
}
printf("%d %c\n",Rank[query][k] , course[k]);
}
}
return 0;
}
补充:关于数字处理的一些技巧
1.向上取整:ceil()
2.向下取整:floor()
3.四舍五入:round()
4.保留有效数字位的写法
#include<stdio.h>
#include<math.h>
int main()
{
double x=1.5684;
printf("对1.5684保留两位有效数字:");
printf("%.2lf\n",round(x*100)/100);
return 0;
}
输出结果:
对1.5684保留两位有效数字:1.57
手写round函数:
#include<stdio.h>
double round(double x)
{
return (int)(x+0.5);
}
A1016
本题是一道比较难的题目。读入数据时可以用bool的true和false来替换on/off-line。先将同一个名字的数据排序到一起,所以cmp首先考虑name的排序其次是month,dd,mm。处理数据是一个难题,首先用三个指针,on,off,next。next用于表示一个用户开始地址,在第一个循环时next指针一边搜索下一个用户的开始地址一边搜索能不能输出。在判断能不能输出时分成两部先找到on-line同时下一个是off-line的时候则能输出。
while(next < n && strcmp(rec[on].name, rec[next].name) == 0)
{
if(rec[next].status == true && rec[next + 1].status == false && strcmp(rec[next + 1].name, rec[next].name) == 0)
flag = true;
next++;
}
可以按上面这种方法写,括号里的最后一个strcmp==0是为了保证是同一个用户。也可以分成两部来写,用int<2判断。
第一个用户已经遍历完了,这是on就可以移动了,判断有无输出。
如果没有输出则后面的直接用continue跳过。如果有输出,从on开始寻找符合输出条件的数据,因为是成对输出所以只需要遍历到next - 2即可,如果on=next-1,说明已经到了最后则更新on进行下一个用户遍历,如果没到说明有输出的满足了。同时写一个记录time和money 的函数,用引用参数即可。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1010;
int toll[25] = {0};
struct Record
{
char name[25];
int month, dd, hh, mm;
bool status;
}rec[N], temp;
bool cmp(Record a, Record b)
{
int s= strcmp(a.name, b.name);
if(s != 0) return s < 0;
else if(a.month != b.month) return a.month < b.month;
else if(a.dd != b.dd) return a.dd < b.dd;
else if(a.hh != b.hh) return a.hh < b.hh;
else return a.mm < b.mm;
}
void get_ans(int on, int off, int& time, int& money)
{
temp = rec[on];
while(temp.dd < rec[off].dd || temp.hh < rec[off].hh || temp.mm < rec[off].mm)
{
time++;
money += toll[temp.hh];
temp.mm++;
if(temp.mm >= 60)
{
temp.mm = 0;
temp.hh++;
}
if(temp.hh >= 24)
{
temp.hh = 0;
temp.dd++;
}
}
}
int main()
{
for(int i = 0; i < 24; i++)
{
scanf("%d", &toll[i]);
}
int n;
char line[10];
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%s", rec[i].name);
scanf("%d:%d:%d:%d", &rec[i].month, &rec[i].dd, &rec[i].hh, &rec[i].mm);
scanf("%s", line);
if(strcmp(line, "on-line") == 0)
rec[i].status = true;
else
rec[i].status = false;
}
sort(rec, rec + n, cmp);
int on = 0, next, off;
while(on < n)
{
int needPrint = 0;
next = on;
while(next < n && strcmp(rec[next].name, rec[on].name) == 0)
{
if(needPrint == 0 && rec[next].status == true)
needPrint = 1;
else if(needPrint == 1 && rec[next].status == false)
needPrint = 2;
next++;
}
if(needPrint < 2)
{
on = next;
continue;
}
int Allmoney = 0;
printf("%s %02d\n", rec[on].name, rec[on].month);
while(on < next)
{
while(on < next - 1 && !(rec[on].status == true && rec[on + 1].status == false))
on++;
off = on + 1;
if(off == next)
{
on = next;
break;
}
int money = 0, time = 0;
printf("%02d:%02d:%02d ", rec[on].dd, rec[on].hh, rec[on].mm);
printf("%02d:%02d:%02d ", rec[off].dd, rec[off].hh, rec[off].mm);
get_ans(on, off, time, money);
Allmoney += money;
printf("%d $%.2f\n", time, money / 100.0);
on = off + 1;
}
printf("Total amount: $%.2f\n", Allmoney / 100.0);
}
return 0;
}
A1055
本题需要预处理,因为告诉我们输出m个所以我们需要将age的前m个放入另一个数组,其余的可以直接丢弃了。但是需要先将整个数组进行sort排序再进行预处理,否则valid数组里的不一定是worth排名前100的数据。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 100010;
int age[200] = {0};
struct Person
{
char name[10];
int age;
int worth;
}per[N],valid[N];
bool cmp(Person a, Person b)
{
if(a.worth != b.worth) return a.worth > b.worth;
else if(a.age != b.age) return a.age < b.age;
else return strcmp(a.name, b.name) < 0;
}
int main()
{
int n, k;
scanf("%d %d", &n, &k);
for(int i = 0; i < n; i++)
{
scanf("%s %d %d", per[i].name, &per[i].age, &per[i].worth);
}
sort(per, per + n, cmp);
int validnum = 0;
for(int i = 0; i < n; i++)
{
if(age[per[i].age] < 100)
{
valid[validnum++] = per[i];
age[per[i].age]++;
}
}
for(int i = 1; i <= k; i++)
{
int m, amin, amax;
scanf("%d %d %d", &m, &amin, &amax);
printf("Case #%d:\n", i);
int printnum = 0;
for(int j = 0; j < validnum && printnum < m; j++)
{
if(valid[j].age >= amin && valid[j].age <= amax)
{
printf("%s %d %d\n", valid[j].name, valid[j].age, valid[j].worth);
printnum ++;
}
}
if(printnum == 0)
printf("None\n");
}
return 0;
}
A1028
写三个cmp函数即可
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Record
{
int id;
char name[10];
int score;
}stu[100010];
bool cmp1(Record a, Record b)
{
return a.id < b.id;
}
bool cmp2(Record a, Record b)
{
int s = strcmp(a.name, b.name);
if(s != 0) return s < 0;
else return a.id < b.id;
}
bool cmp3(Record a, Record b)
{
if(a.score != b.score) return a.score < b.score;
else return a.id < b.id;
}
int main()
{
int n, c;
scanf("%d %d", &n, &c);
for(int i = 0; i < n; i++)
{
scanf("%d %s %d", &stu[i].id, stu[i].name, &stu[i].score);
}
if(c == 1) sort(stu, stu + n, cmp1);
if(c == 2) sort(stu, stu + n, cmp2);
if(c == 3) sort(stu, stu + n, cmp3);
for(int i = 0; i < n; i++)
{
printf("%06d %s %d\n", stu[i].id, stu[i].name, stu[i].score);
}
return 0;
}
A1025
设置locarank,final_rank最后用个r来表示,同时用num来和k来确定每次读入数据的范围【num-k,num】。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct student
{
char id[15];
int score;
int localnumber;
int localrank;
}stu[30010];
bool cmp(student a, student b)
{
if(a.score != b.score) return a.score > b.score;
else return strcmp(a.id, b.id) < 0;
}
int main()
{
int n, k, num = 0;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%d", &k);
for(int j = 0; j < k; j++)
{
scanf("%s %d", stu[num].id, &stu[num].score);
stu[num].localnumber = i;
num ++;
}
sort(stu + num - k, stu + num, cmp);
stu[num - k].localrank = 1;
for(int j = num - k + 1; j < num; j++)
{
if(stu[j].score == stu[j - 1].score)
{
stu[j].localrank = stu[j - 1].localrank;
}else
stu[j].localrank = j + 1 - (num - k);
}
}
printf("%d\n", num);
sort(stu, stu + num, cmp);
int r = 1;
for(int i = 0; i < num; i++)
{
if(i > 0 && stu[i].score != stu[i - 1].score)
r = i + 1;
printf("%s ", stu[i].id);
printf("%d %d %d\n", r, stu[i].localnumber, stu[i].localrank);
}
return 0;
}
A1075
本题由于要区分没有提交和编译不通过的情况,以及是否能够输出。所以先设置一个bool变量用于确定是否输出。由于id是从1到n所以可以用u_id读入后直接将score赋值到以u_id为下标的数组元素。同时需要定义sum和solve,在每次读入一个数据时对以u_id的这个元素进行更新。首先判断如果可以输出让bool变量为true,其次为了判定是为提交还是编译不通过,初始化score为-1,获得的分数为-1并且score为-1,则让score为0,所以最后如果为-1说明未提交,如果是0说明为编译未通过。 如果是第一次达到满分则solve++,如果当前分数比score存储的大,则覆盖。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 10010;
int n, m, k;
int full[6];
struct Student
{
int id;
int solve;
int score[6];
int sum;
bool status;
}stu[N];
bool cmp(Student a, Student b)
{
if(a.sum != b.sum) return a.sum > b.sum;
else if(a.solve != b.solve) return a.solve > b.solve;
else return a.id < b.id;
}
void init()
{
for(int i = 1; i <= n; i++)
{
stu[i].sum = 0 ;
stu[i].id = i;
stu[i].solve = 0;
stu[i].status = false;
memset(stu[i].score, -1, sizeof(stu[i].score));
}
}
int main()
{
scanf("%d%d%d", &n, &k, &m);
init();
for(int i = 1; i <= k; i++)
scanf("%d", &full[i]);
for(int i = 1; i <= m; i++)
{
int u_id, p_id, gain_score;
scanf("%d %d %d", &u_id, &p_id, &gain_score);
if(gain_score != -1)
stu[u_id].status = true;
if(gain_score == -1 && stu[u_id].score[p_id] == -1)
stu[u_id].score[p_id] = 0;
if(gain_score == full[p_id] && stu[u_id].score[p_id] != full[p_id])
stu[u_id].solve++;
if(gain_score > stu[u_id].score[p_id])
stu[u_id].score[p_id] = gain_score;
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= k; j++)
if(stu[i].score[j] != -1)
stu[i].sum += stu[i].score[j];
}
sort(stu + 1, stu + n + 1, cmp);
int r = 1;
for(int i = 1; i <= n && stu[i].status == true; i++)
{
if(i > 1 && stu[i].sum != stu[i - 1].sum)
r = i;
printf("%d %05d %d", r, stu[i].id, stu[i].sum);
for(int j = 1; j <= k; j++)
{
if(stu[i].score[j] == -1)
printf(" -");
else
printf(" %d", stu[i].score[j]);
}
printf("\n");
}
return 0;
}
A1083
水题
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct Student
{
char name[15];
char id[15];
int score;
}stu[110];
bool cmp(Student a, Student b)
{
return a.score > b.score;
}
int main()
{
int n, left, right;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%s %s %d", stu[i].name, stu[i].id, &stu[i].score);
}
scanf("%d %d",&left, &right);
bool print = false;
sort(stu + 1, stu + n + 1, cmp);
for(int i = 1; i <= n; i++)
{
if(stu[i].score >= left && stu[i].score <= right)
{
printf("%s %s\n", stu[i].name, stu[i].id);
print = true;
}
}
if(!print)
printf("NONE\n");
return 0;
}
A1080
本题需要写两个结构体,一个是学生,一个是学校。因为要考虑到学校找人超出的情况,所以需要在学校的结构体内设置指标,人数和上一个录取人的信息。又因为sort以后每个学生的下标就变了,所以要以学生内部需要设置id来记录是第几个被输入的用于后面被输出。在所有信息读入后,先对学生的rank进行处理,然后对每一个学生进行外循环,对学生的每个志愿进行内循环。先读入志愿学校的标号,志愿和该学校最后一个录取的人数的序号。根据条件判断能否录取,如果能够录取则把该学生在排好序的数组的下标读入到学校的id数组里用于最后输出原来的下标。并且更新num和lastadmit。最后遍历学校,如果学校的的招生人数大于0则排序并进行输出。
#include<cstdio>
#include<algorithm>
using namespace std;
struct Student
{
int GE, GI, sum;
int r, stuID;
int cho[6];
}stu[40010];
struct School
{
int quota;
int stuNum;
int lastAdmit;
int ID[40010];
}sch[110];
bool cmpStu(Student a, Student b)
{
if(a.sum != b.sum) return a.sum > b.sum;
else return a.GE > b.GE;
}
bool cmpID(int a, int b)
{
return stu[a].stuID < stu[b].stuID;
}
int main()
{
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
for(int i = 0; i < m; i++)
{
scanf("%d", &sch[i].quota);
sch[i].stuNum = 0;
sch[i].lastAdmit = -1;
}
for(int i = 0; i < n; i++)
{
scanf("%d%d", &stu[i].GE, &stu[i].GI);
stu[i].sum = stu[i].GE + stu[i].GI;
stu[i].stuID = i;
for(int j = 0; j < k; j++)
scanf("%d", &stu[i].cho[j]);
}
sort(stu, stu + n, cmpStu);
for(int i = 0; i < n; i++)
{
if(i > 0 && stu[i].sum == stu[i-1].sum && stu[i].GE == stu[i-1].GE)
stu[i].r = stu[i - 1].r;
else
stu[i].r = i;
}
for(int i = 0; i < n; i++)
{
for(int j = 0; j < k; j++)
{
int choice = stu[i].cho[j];
int last = sch[choice].lastAdmit;
int num = sch[choice].stuNum;
if(num < sch[choice].quota || (stu[i].r == stu[last].r))
{
sch[choice].ID[num] = i;
sch[choice].lastAdmit = i;
sch[choice].stuNum++;
break;
}
}
}
for(int i = 0; i < m; i++)
{
if(sch[i].stuNum > 0)
{
sort(sch[i].ID, sch[i].ID + sch[i].stuNum, cmpID);
for(int j = 0; j < sch[i].stuNum; j++)
{
printf("%d", stu[sch[i].ID[j]].stuID);
if(j < sch[i].stuNum - 1)
printf(" ");
}
}
printf("\n");
}
return 0;
}
A1095
本题和A1016相似,都是处理相同名字的多个数据。由于需要输出最大的停车时间所以需要建立一个string到int 的map映射。time直接用秒做单位会化简很多代码。首先读入数据排序,在遍历的时候把in和out配对的存入另一个数组并且不断更新maxtime的值。因为这个是以同一个车牌的不同时间的处理。所以可以得到每个车的总时间。然后对有效数组按时间进行排序,因为给的查询时间是递增的所以每次不需要初始化0,上一个循环可以继续的参数可以继续使用。遇到in时numcar加1遇到out时numcar减1.最后用迭代器遍历map。找到最大时间的下标输出即可。注意输出格式需要用char数组的格式。
#include<cstdio>
#include<map>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
const int N = 10010;
struct Car
{
char id[10];
int time;
char status[5];
}all[N], valid[N];
map<string, int>parkTime;
int timeToInt(int hh, int mm, int ss)
{
return hh * 3600 + mm * 60 + ss;
}
bool cmpByCarAndTime(Car a, Car b)
{
int s = strcmp(a.id, b.id);
if(s != 0) return s < 0;
else return a.time < b.time;
}
bool cmpByTime(Car a, Car b)
{
return a.time < b.time;
}
int main()
{
int n, k, hh, mm, ss;
scanf("%d%d%d", &n, &k);
for(int i = 0; i < n; i++)
{
scanf("%s %d:%d:%d %s", all[i].id, &hh, &mm, &ss, all[i].status);
all[i].time = timeToInt(hh, mm, ss);
}
sort(all, all + n, cmpByCarAndTime);
int num = 0, maxtime = -1;
for(int i = 0; i < n; i++)
{
if(!strcmp(all[i].id, all[i+1].id) &&
!strcmp(all[i].status, "in") &&
!strcmp(all[i + 1].status, "out"))
{
valid[num++] = all[i];
valid[num++] = all[i + 1];
int intime = all[i + 1].time - all[i].time;
if(parkTime.count(all[i].id) == 0)
parkTime[all[i].id] = 0;
parkTime[all[i].id] += intime;
maxtime = max(maxtime, parkTime[all[i].id]);
}
}
sort(valid, valid + num, cmpByTime);
int now = 0, carNum = 0;
for(int i = 0; i < k; i++)
{
scanf("%d:%d:%d", &hh, &mm, &ss);
int time = timeToInt(hh, mm, ss);
while(now < num && valid[now].time <= time)
{
if(strcmp(valid[now].status, "in") == 0) carNum++;
else carNum--;
now++;
}
printf("%d\n", carNum);
}
map<string, int>::iterator it;
for(it = parkTime.begin(); it != parkTime.end(); it++)
{
if(it->second == maxtime)
printf("%s ", it->first.c_str());
}
printf("%02d:%02d:%02d", maxtime/3600, maxtime%3600/60, maxtime%60);
return 0;
}