2-1 直接插入排序
分数 4
作者 DS课程组
单位 临沂大学
本题要求实现直接插入排序函数,待排序列的长度1<=n<=1000。
函数接口定义:
void InsertSort (SqList L) ;
其中L是待排序表,使排序后的数据从小到大排列。
###类型定义:
typedef int KeyType;typedef struct { KeyType *elem; int Length; }SqList;
裁判测试程序样例:
#include <stdio.h> #include <stdlib.h> typedef int KeyType;typedef struct { KeyType *elem; int Length; }SqList; void CreatSqList (SqList *L) ; void InsertSort (SqList L) ;int main () { SqList L; int i; CreatSqList (&L); InsertSort (L); for (i=1 ;i<=L.Length;i++) { printf ("%d " ,L.elem[i]); } return 0 ; }
输入样例:
第一行整数表示参与排序的关键字个数。第二行是关键字值 例如:
输出样例:
输出由小到大的有序序列,每一个关键字之间由空格隔开,最后一个关键字后有一个空格。
解析
void InsertSort (SqList L) { int i, j; for (i = 2 ; i <= L.Length; ++i) { if (L.elem[i] < L.elem[i-1 ]) { L.elem[0 ] = L.elem[i]; for (j = i - 1 ; L.elem[j] > L.elem[0 ]; --j) { L.elem[j+1 ] = L.elem[j]; } L.elem[j+1 ] = L.elem[0 ]; } } }
2-2 希尔排序的实现
分数 4
作者 DS课程组
单位 临沂大学
本题要求实现一趟希尔排序函数,待排序列的长度1<=n<=1000。
函数接口定义:
void ShellInsert (SqList L,int dk) ;
其中L是待排序表,使排序后的数据从小到大排列。
###类型定义:
typedef int KeyType;typedef struct { KeyType *elem; int Length; }SqList;
裁判测试程序样例:
#include <stdio.h> #include <stdlib.h> typedef int KeyType;typedef struct { KeyType *elem; int Length; }SqList; void CreatSqList (SqList *L) ; void ShellInsert (SqList L,int dk) ;void ShellSort (SqList L) ;int main () { SqList L; int i; CreatSqList (&L); ShellSort (L); for (i=1 ;i<=L.Length;i++) { printf ("%d " ,L.elem[i]); } return 0 ; } void ShellSort (SqList L) { int k; int dlta[3 ]={5 ,3 ,1 }; int t=3 ; for (k=0 ;k<t;++k) ShellInsert (L,dlta[k]); }
输入样例:
第一行整数表示参与排序的关键字个数。第二行是关键字值 例如:
输出样例:
输出由小到大的有序序列,每一个关键字之间由空格隔开,最后一个关键字后有一个空格。
解析
void ShellInsert (SqList L, int dk) { int i, j; for (i = dk + 1 ; i <= L.Length; ++i) { if (L.elem[i] < L.elem[i - dk]) { L.elem[0 ] = L.elem[i]; for (j = i - dk; j > 0 && L.elem[j] > L.elem[0 ]; j -= dk) { L.elem[j + dk] = L.elem[j]; } L.elem[j + dk] = L.elem[0 ]; } } }
2-3 冒泡排序
分数 4
作者 DS课程组
单位 临沂大学
本题要求实现冒泡排序函数,待排序列的长度1<=n<=1000。
函数接口定义:
void bubble_sort (SqList L) ;
其中L是待排序表,使排序后的数据从小到大排列。
###类型定义:
typedef int KeyType;typedef struct { KeyType *elem; int Length; }SqList;
裁判测试程序样例:
#include <stdio.h> #include <stdlib.h> typedef int KeyType;typedef struct { KeyType *elem; int Length; }SqList; void CreatSqList (SqList *L) ; void bubble_sort (SqList L) ;int main () { SqList L; int i; CreatSqList (&L); bubble_sort ( L); for (i=1 ;i<=L.Length;i++) { printf ("%d " ,L.elem[i]); } return 0 ; }
输入样例:
第一行整数表示参与排序的关键字个数。第二行是关键字值 例如:
输出样例:
输出由小到大的有序序列,每一个关键字之间由空格隔开,最后一个关键字后有一个空格。
解析
void bubble_sort (SqList L) { int i, j; int flag; for (i = 1 ; i < L.Length; ++i) { flag = 0 ; for (j = 1 ; j <= L.Length - i; ++j) { if (L.elem[j] > L.elem[j + 1 ]) { int temp = L.elem[j]; L.elem[j] = L.elem[j + 1 ]; L.elem[j + 1 ] = temp; flag = 1 ; } } if (flag == 0 ) { break ; } } }
2-4 快速排序
分数 4
作者 DS课程组
单位 临沂大学
本题要求实现快速排序的一趟划分函数,待排序列的长度1<=n<=1000。
函数接口定义:
int Partition ( SqList L, int low, int high ) ;
其中L是待排序表,使排序后的数据从小到大排列。
###类型定义:
typedef int KeyType;typedef struct { KeyType *elem; int Length; }SqList;
裁判测试程序样例:
#include <stdio.h> #include <stdlib.h> typedef int KeyType;typedef struct { KeyType *elem; int Length; }SqList; void CreatSqList (SqList *L) ; int Partition ( SqList L,int low, int high ) ;void Qsort ( SqList L,int low, int high ) ;int main () { SqList L; int i; CreatSqList (&L); Qsort (L,1 ,L.Length); for (i=1 ;i<=L.Length;i++) printf ("%d " ,L.elem[i]); return 0 ; } void Qsort ( SqList L,int low, int high ) { int pivotloc; if (low<high) { pivotloc = Partition (L, low, high ) ; Qsort (L, low, pivotloc-1 ) ; Qsort (L, pivotloc+1 , high ); } }
输入样例:
第一行整数表示参与排序的关键字个数。第二行是关键字值 例如:
输出样例:
输出由小到大的有序序列,每一个关键字之间由空格隔开,最后一个关键字后有一个空格。
解析
int Partition (SqList L, int low, int high) { KeyType pivot = L.elem[high]; int i = low - 1 ; for (int j = low; j < high; j++) { if (L.elem[j] <= pivot) { i++; KeyType temp = L.elem[i]; L.elem[i] = L.elem[j]; L.elem[j] = temp; } } KeyType temp = L.elem[i + 1 ]; L.elem[i + 1 ] = L.elem[high]; L.elem[high] = temp; return i + 1 ; }
2-5 简单选择排序
分数 4
作者 DS课程组
单位 临沂大学
本题要求实现简单选择排序函数,待排序列的长度1<=n<=1000。
函数接口定义:
void SelectSort (SqList L) ;
其中L是待排序表,使排序后的数据从小到大排列。
类型定义:
typedef int KeyType;typedef struct { KeyType *elem; int Length; }SqList;
裁判测试程序样例:
#include <stdio.h> #include <stdlib.h> typedef int KeyType;typedef struct { KeyType *elem; int Length; }SqList; void CreatSqList (SqList *L) ; void SelectSort (SqList L) ;int main () { SqList L; int i; CreatSqList (&L); SelectSort (L); for (i=1 ;i<=L.Length;i++) { printf ("%d " ,L.elem[i]); } return 0 ; }
输入样例:
第一行整数表示参与排序的关键字个数。第二行是关键字值 例如:
输出样例:
输出由小到大的有序序列,每一个关键字之间由空格隔开,最后一个关键字后有一个空格。
解析
void SelectSort (SqList L) { int i, j, min_idx; for (i = 1 ; i < L.Length; ++i) { min_idx = i; for (j = i + 1 ; j <= L.Length; ++j) { if (L.elem[j] < L.elem[min_idx]) { min_idx = j; } } if (min_idx != i) { int temp = L.elem[i]; L.elem[i] = L.elem[min_idx]; L.elem[min_idx] = temp; } } }
2-6 堆排序
分数 4
作者 DS课程组
单位 临沂大学
本题要求实现堆排序中的筛选函数,待排序列的长度1<=n<=1000。
函数接口定义:
void HeapAdjust ( HeapType H, int s, int m) ;
其中L是待排序表,使排序后的数据从小到大排列。
类型定义:
typedef int KeyType;typedef struct { KeyType *elem; int Length; }SqList; typedef SqList HeapType;
裁判测试程序样例:
#include <stdio.h> #include <stdlib.h> typedef int KeyType;typedef struct { KeyType *elem; int Length; }SqList; typedef SqList HeapType; void CreatSqListHeapType *L); void HeapAdjust ( HeapType H, int s, int m) ;void HeapSort ( HeapType H) ;int main () { HeapType L; int i; CreatSqList (&L); HeapSort (L); for (i=1 ;i<=L.Length;i++) { printf ("%d " ,L.elem[i]); } return 0 ; } void HeapSort ( HeapType H) { int i; KeyType rc; for ( i=H.Length/2 ;i>0 ; i--) { HeapAdjust (H, i, H.Length); } for (i=H.Length;i>1 ;i--) { rc=H.elem[1 ]; H.elem[1 ]=H.elem[i]; H.elem[i]=rc; HeapAdjust (H, 1 , i-1 ); } }
输入样例:
第一行整数表示参与排序的关键字个数。第二行是关键字值 例如:
输出样例:
输出由小到大的有序序列,每一个关键字之间由空格隔开,最后一个关键字后有一个空格。
解析
void HeapAdjust (HeapType H, int s, int m) { KeyType rc = H.elem[s]; int j; for (j = 2 * s; j <= m; j *= 2 ) { if (j < m && H.elem[j] < H.elem[j + 1 ]) { j++; } if (rc >= H.elem[j]) { break ; } H.elem[s] = H.elem[j]; s = j; } H.elem[s] = rc; }
2-7 归并排序
分数 4
作者 DS课程组
单位 临沂大学
本题要求实现二路归并排序中的归并操作,待排序列的长度1<=n<=1000。
函数接口定义:
void Merge (SqList L,int low,int m,int high) ;
其中L是待排序表,使排序后的数据从小到大排列。
类型定义:
#include <stdio.h> #include <stdlib.h> typedef int KeyType;typedef struct { KeyType *elem; int Length; }SqList; void CreatSqList (SqList *L) ; void MergeSort (SqList L,int low,int high) ;void Merge (SqList L,int low,int m,int high) ; int main () { SqList L; int i; CreatSqList (&L); MergeSort (L,1 ,L.Length); for (i=1 ;i<=L.Length;i++) { printf ("%d " ,L.elem[i]); } return 0 ; } void MergeSort (SqList L,int low,int high) { int mid; if (low<high) { mid=(low+high)/2 ; MergeSort (L,low,mid); MergeSort (L,mid+1 ,high); Merge (L,low,mid,high); } }
输入样例:
第一行整数表示参与排序的关键字个数。第二行是关键字值 例如:
输出样例:
输出由小到大的有序序列,每一个关键字之间由空格隔开,最后一个关键字后有一个空格。
解析
void Merge (SqList L, int low, int m, int high) { int i = low; int j = m + 1 ; int k = 0 ; int len = high - low + 1 ; int *temp = (int *)malloc (len * sizeof (int )); while (i <= m && j <= high) { if (L.elem[i] <= L.elem[j]) { temp[k++] = L.elem[i++]; } else { temp[k++] = L.elem[j++]; } } while (i <= m) { temp[k++] = L.elem[i++]; } while (j <= high) { temp[k++] = L.elem[j++]; } for (k = 0 ; k < len; k++) { L.elem[low + k] = temp[k]; } free (temp); }
3-1 排序
分数 9
作者 陈越
单位 浙江大学
给定 n 个(长整型范围内的)整数,要求输出从小到大排序后的结果。
本题旨在测试各种不同的排序算法在各种数据情况下的表现。各组测试数据特点如下:
数据1:只有1个元素;
数据2:11个不相同的整数,测试基本正确性;
数据3:103个随机整数;
数据4:104个随机整数;
数据5:105个随机整数;
数据6:105个顺序整数;
数据7:105个逆序整数;
数据8:105个基本有序的整数;
数据9:105个随机正整数,每个数字不超过1000。
输入格式:
输入第一行给出正整数 n (≤105),随后一行给出 n 个(长整型范围内的)整数,其间以空格分隔。
输出格式:
在一行中输出从小到大排序后的结果,数字间以 1 个空格分隔,行末不得有多余空格。
输入样例:
11 4 981 10 -17 0 -20 29 50 8 43 -5
输出样例:
-20 -17 -5 0 4 8 10 29 43 50 981
解析
#include <iostream> #include <vector> #include <algorithm> using namespace std;int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ); int n; cin >> n; vector<long long > nums (n) ; for (int i = 0 ; i < n; ++i) { cin >> nums[i]; } sort (nums.begin (), nums.end ()); for (int i = 0 ; i < n; ++i) { if (i > 0 ) { cout << " " ; } cout << nums[i]; } return 0 ; }
3-2 寻找大富翁
分数 9
作者 陈越
单位 浙江大学
胡润研究院的调查显示,截至2017年底,中国个人资产超过1亿元的高净值人群达15万人。假设给出N个人的个人资产值,请快速找出资产排前M位的大富翁。
输入格式:
输入首先给出两个正整数N (≤106)和M (≤10),其中N 为总人数,M 为需要找出的大富翁数;接下来一行给出N 个人的个人资产值,以百万元为单位,为不超过长整型范围的整数。数字间以空格分隔。
输出格式:
在一行内按非递增顺序输出资产排前M 位的大富翁的个人资产值。数字间以空格分隔,但结尾不得有多余空格。
输入样例:
输出样例:
解析
#include <stdio.h> #include <stdlib.h> void heapify (long long heap[], int size, int i) { int min_idx = i; while (1 ) { int left = 2 * i + 1 ; int right = 2 * i + 2 ; if (left < size && heap[left] < heap[min_idx]) { min_idx = left; } if (right < size && heap[right] < heap[min_idx]) { min_idx = right; } if (min_idx != i) { long long temp = heap[i]; heap[i] = heap[min_idx]; heap[min_idx] = temp; i = min_idx; } else { break ; } } } void build_min_heap (long long heap[], int size) { for (int i = size / 2 - 1 ; i >= 0 ; i--) { heapify (heap, size, i); } } int main () { int N, M; scanf ("%d %d" , &N, &M); long long *heap = (long long *)malloc (M * sizeof (long long )); int count = 0 ; for (int i = 0 ; i < N; i++) { long long x; scanf ("%lld" , &x); if (count < M) { heap[count++] = x; if (count == M) { build_min_heap (heap, M); } } else { if (x > heap[0 ]) { heap[0 ] = x; heapify (heap, M, 0 ); } } } for (int i = 0 ; i < count; i++) { for (int j = i + 1 ; j < count; j++) { if (heap[i] < heap[j]) { long long temp = heap[i]; heap[i] = heap[j]; heap[j] = temp; } } } for (int i = 0 ; i < count; i++) { if (i > 0 ) { printf (" " ); } printf ("%lld" , heap[i]); } printf ("\n" ); free (heap); return 0 ; }
3-3 统计工龄
分数 9
作者 陈越
单位 浙江大学
给定公司 n 名员工的工龄,要求按工龄增序输出每个工龄段有多少员工。
输入格式:
输入首先给出正整数 n (≤105),即员工总人数;随后给出 n 个整数,即每个员工的工龄,范围在 [0, 50]。
输出格式:
按工龄的递增顺序输出每个工龄的员工个数,格式为:“工龄:人数”。每项占一行。如果人数为 0 则不输出该项。
输入样例:
输出样例:
解析
#include <iostream> using namespace std;int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ); const int MAX_AGE = 50 ; int count[MAX_AGE + 1 ] = {0 }; int n; cin >> n; for (int i = 0 ; i < n; ++i) { int age; cin >> age; count[age]++; } for (int age = 0 ; age <= MAX_AGE; ++age) { if (count[age] > 0 ) { cout << age << ":" << count[age] << "\n" ; } } return 0 ; }
3-4 奥运排行榜
分数 9
作者 陈越
单位 浙江大学
每年奥运会各大媒体都会公布一个排行榜,但是细心的读者发现,不同国家的排行榜略有不同。比如中国金牌总数列第一的时候,中国媒体就公布“金牌榜”;而美国的奖牌总数第一,于是美国媒体就公布“奖牌榜”。如果人口少的国家公布一个“国民人均奖牌榜”,说不定非洲的国家会成为榜魁…… 现在就请你写一个程序,对每个前来咨询的国家按照对其最有利的方式计算它的排名。
输入格式:
输入的第一行给出两个正整数N 和M (≤224,因为世界上共有224个国家和地区),分别是参与排名的国家和地区的总个数、以及前来咨询的国家的个数。为简单起见,我们把国家从0 ~ N −1编号。之后有N 行输入,第i 行给出编号为i −1的国家的金牌数、奖牌数、国民人口数(单位为百万),数字均为[0,1000]区间内的整数,用空格分隔。最后面一行给出M 个前来咨询的国家的编号,用空格分隔。
输出格式:
在一行里顺序输出前来咨询的国家的排名:计算方式编号。其排名按照对该国家最有利的方式计算;计算方式编号为:金牌榜=1,奖牌榜=2,国民人均金牌榜=3,国民人均奖牌榜=4。输出间以空格分隔,输出结尾不能有多余空格。
若某国在不同排名方式下有相同名次,则输出编号最小的计算方式。
输入样例:
4 4 51 100 1000 36 110 300 6 14 32 5 18 40 0 1 2 3
输出样例:
解析
#include <iostream> #include <vector> #include <algorithm> using namespace std;struct Country { int gold; int total; int pop; int ranks[5 ]; }; int main () { int N, M; if (!(cin >> N >> M)) return 0 ; vector<Country> countries (N) ; for (int i = 0 ; i < N; ++i) { cin >> countries[i].gold >> countries[i].total >> countries[i].pop; } vector<int > indices (N) ; for (int m = 1 ; m <= 4 ; ++m) { for (int i = 0 ; i < N; ++i) indices[i] = i; sort (indices.begin (), indices.end (), [&](int a, int b) { if (m == 1 ) return countries[a].gold > countries[b].gold; if (m == 2 ) return countries[a].total > countries[b].total; if (m == 3 ) { return (long long )countries[a].gold * countries[b].pop > (long long )countries[b].gold * countries[a].pop; } return (long long )countries[a].total * countries[b].pop > (long long )countries[b].total * countries[a].pop; }); countries[indices[0 ]].ranks[m] = 1 ; for (int i = 1 ; i < N; ++i) { int curID = indices[i]; int prevID = indices[i-1 ]; bool isTied = false ; if (m == 1 ) isTied = (countries[curID].gold == countries[prevID].gold); else if (m == 2 ) isTied = (countries[curID].total == countries[prevID].total); else if (m == 3 ) { isTied = ((long long )countries[curID].gold * countries[prevID].pop == (long long )countries[prevID].gold * countries[curID].pop); } else { isTied = ((long long )countries[curID].total * countries[prevID].pop == (long long )countries[prevID].total * countries[curID].pop); } if (isTied) { countries[curID].ranks[m] = countries[prevID].ranks[m]; } else { countries[curID].ranks[m] = i + 1 ; } } } for (int i = 0 ; i < M; ++i) { int queryID; cin >> queryID; int bestRank = N + 1 ; int bestMethod = 1 ; for (int m = 1 ; m <= 4 ; ++m) { if (countries[queryID].ranks[m] < bestRank) { bestRank = countries[queryID].ranks[m]; bestMethod = m; } } if (i > 0 ) cout << " " ; cout << bestRank << ":" << bestMethod; } return 0 ; }
3-5 PAT排名汇总
分数 9
作者 陈越
单位 浙江大学
计算机程序设计能力考试(Programming Ability Test,简称PAT)旨在通过统一组织的在线考试及自动评测方法客观地评判考生的算法设计与程序设计实现能力,科学的评价计算机程序设计人才,为企业选拔人才提供参考标准(网址http://www.patest.cn)。
每次考试会在若干个不同的考点同时举行,每个考点用局域网,产生本考点的成绩。考试结束后,各个考点的成绩将即刻汇总成一张总的排名表。
现在就请你写一个程序自动归并各个考点的成绩并生成总排名表。
输入格式:
输入的第一行给出一个正整数N(≤100),代表考点总数。随后给出N个考点的成绩,格式为:首先一行给出正整数K(≤300),代表该考点的考生总数;随后K行,每行给出1个考生的信息,包括考号(由13位整数字组成)和得分(为[0,100]区间内的整数),中间用空格分隔。
输出格式:
首先在第一行里输出考生总数。随后输出汇总的排名表,每个考生的信息占一行,顺序为:考号、最终排名、考点编号、在该考点的排名。其中考点按输入给出的顺序从1到N编号。考生的输出须按最终排名的非递减顺序输出,获得相同分数的考生应有相同名次,并按考号的递增顺序输出。
输入样例:
2 5 1234567890001 95 1234567890005 100 1234567890033 95 1234567890002 77 1234567890004 85 4 1234567890013 95 1234567890011 25 1234567890014 100 1234567890042 95
输出样例:
9 1234567890005 1 1 1 1234567890014 1 2 1 1234567890001 3 1 2 1234567890013 3 2 2 1234567890033 3 1 2 1234567890042 3 2 2 1234567890004 7 1 4 1234567890002 8 1 5 1234567890011 9 2 4
解析
#include <bits/stdc++.h> using namespace std;struct Student { string id; int score; int location; int local_rank; int final_rank; }; bool cmp (const Student &a, const Student &b) { if (a.score != b.score) return a.score > b.score; return a.id < b.id; } int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ); int N; cin >> N; vector<Student> all; for (int loc = 1 ; loc <= N; loc++) { int K; cin >> K; vector<Student> local (K) ; for (int i = 0 ; i < K; i++) { cin >> local[i].id >> local[i].score; local[i].location = loc; } sort (local.begin (), local.end (), cmp); local[0 ].local_rank = 1 ; for (int i = 1 ; i < K; i++) { if (local[i].score == local[i - 1 ].score) local[i].local_rank = local[i - 1 ].local_rank; else local[i].local_rank = i + 1 ; } for (auto &x : local) all.push_back (x); } sort (all.begin (), all.end (), cmp); all[0 ].final_rank = 1 ; for (int i = 1 ; i < (int )all.size (); i++) { if (all[i].score == all[i - 1 ].score) all[i].final_rank = all[i - 1 ].final_rank; else all[i].final_rank = i + 1 ; } cout << all.size () << "\n" ; for (auto &x : all) { cout << x.id << " " << x.final_rank << " " << x.location << " " << x.local_rank << "\n" ; } return 0 ; }
3-6 抢红包
分数 9
作者 陈越
单位 浙江大学
没有人没抢过红包吧…… 这里给出N 个人之间互相发红包、抢红包的记录,请你统计一下他们抢红包的收获。
输入格式:
输入第一行给出一个正整数N (≤104),即参与发红包和抢红包的总人数,则这些人从1到N 编号。随后N 行,第i 行给出编号为i 的人发红包的记录,格式如下:
K**N 1P 1⋯NK P**K
其中K (0≤K ≤20)是发出去的红包个数,N**i 是抢到红包的人的编号,P**i (>0)是其抢到的红包金额(以分为单位)。注意:对于同一个人发出的红包,每人最多只能抢1次,不能重复抢。
输出格式:
按照收入金额从高到低的递减顺序输出每个人的编号和收入金额(以元为单位,输出小数点后2位)。每个人的信息占一行,两数字间有1个空格。如果收入金额有并列,则按抢到红包的个数递减输出;如果还有并列,则按个人编号递增输出。
输入样例:
10 3 2 22 10 58 8 125 5 1 345 3 211 5 233 7 13 8 101 1 7 8800 2 1 1000 2 1000 2 4 250 10 320 6 5 11 9 22 8 33 7 44 10 55 4 2 1 3 8800 2 1 23 2 123 1 8 250 4 2 121 4 516 7 112 9 10
输出样例:
1 11.63 2 3.63 8 3.63 3 2.11 7 1.69 6 -1.67 9 -2.18 10 -3.26 5 -3.26 4 -12.32
解析
#include <iostream> #include <vector> #include <algorithm> #include <cstdio> using namespace std;struct Person { int id; long long income; int count; Person () : id (0 ), income (0 ), count (0 ) {} Person (int _id) : id (_id), income (0 ), count (0 ) {} }; int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ); int N; cin >> N; vector<Person> people (N + 1 ) ; for (int i = 1 ; i <= N; ++i) { people[i].id = i; } for (int i = 1 ; i <= N; ++i) { int K; cin >> K; long long sum_paid = 0 ; for (int j = 0 ; j < K; ++j) { int ni, pi; cin >> ni >> pi; sum_paid += pi; people[ni].income += pi; people[ni].count++; } people[i].income -= sum_paid; } sort (people.begin () + 1 , people.end (), [](const Person& a, const Person& b) { if (a.income != b.income) { return a.income > b.income; } else if (a.count != b.count) { return a.count > b.count; } else { return a.id < b.id; } }); for (int i = 1 ; i <= N; ++i) { printf ("%d %.2f\n" , people[i].id, people[i].income / 100.0 ); } return 0 ; }
3-7 点赞狂魔
分数 9
作者 陈越
单位 浙江大学
微博上有个“点赞”功能,你可以为你喜欢的博文点个赞表示支持。每篇博文都有一些刻画其特性的标签,而你点赞的博文的类型,也间接刻画了你的特性。然而有这么一种人,他们会通过给自己看到的一切内容点赞来狂刷存在感,这种人就被称为“点赞狂魔”。他们点赞的标签非常分散,无法体现出明显的特性。本题就要求你写个程序,通过统计每个人点赞的不同标签的数量,找出前3名点赞狂魔。
输入格式:
输入在第一行给出一个正整数N (≤100),是待统计的用户数。随后N 行,每行列出一位用户的点赞标签。格式为“Name K F 1⋯F**K ”,其中Name是不超过8个英文小写字母的非空用户名,1≤K ≤1000,F**i (i =1,⋯,K )是特性标签的编号,我们将所有特性标签从 1 到 107 编号。数字间以空格分隔。
输出格式:
统计每个人点赞的不同标签的数量,找出数量最大的前3名,在一行中顺序输出他们的用户名,其间以1个空格分隔,且行末不得有多余空格。如果有并列,则输出标签出现次数平均值最小的那个,题目保证这样的用户没有并列。若不足3人,则用-补齐缺失,例如mike jenny -就表示只有2人。
输入样例:
5 bob 11 101 102 103 104 105 106 107 108 108 107 107 peter 8 1 2 3 4 3 2 5 1 chris 12 1 2 3 4 5 6 7 8 9 1 2 3 john 10 8 7 6 5 4 3 2 1 7 5 jack 9 6 7 8 9 10 11 12 13 14
输出样例:
解析
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { char name[9 ]; int K; int unique_cnt; } User; int cmp_int (const void *a, const void *b) { return *(int *)a - *(int *)b; } int cmp_user (const void *a, const void *b) { User *u1 = (User *)a; User *u2 = (User *)b; if (u1->unique_cnt != u2->unique_cnt) { return u2->unique_cnt - u1->unique_cnt; } else { long long avg1 = (long long )u1->K * u2->unique_cnt; long long avg2 = (long long )u2->K * u1->unique_cnt; return avg1 - avg2; } } int main () { int N; scanf ("%d" , &N); User users[100 ]; for (int i = 0 ; i < N; i++) { char name[9 ]; int K; scanf ("%s %d" , name, &K); int tags[1000 ]; for (int j = 0 ; j < K; j++) { scanf ("%d" , &tags[j]); } qsort (tags, K, sizeof (int ), cmp_int); int unique = 1 ; for (int j = 1 ; j < K; j++) { if (tags[j] != tags[j-1 ]) { unique++; } } strcpy (users[i].name, name); users[i].K = K; users[i].unique_cnt = unique; } qsort (users, N, sizeof (User), cmp_user); for (int i = 0 ; i < 3 ; i++) { if (i > 0 ) { printf (" " ); } if (i < N) { printf ("%s" , users[i].name); } else { printf ("-" ); } } printf ("\n" ); return 0 ; }
3-8 插入排序还是归并排序
分数 9
作者 陈越
单位 浙江大学
根据维基百科的定义:
插入排序 是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。
归并排序 进行如下迭代操作:首先将原始序列看成 N 个只包含 1 个元素的有序子序列,然后每次迭代归并两个相邻的有序子序列,直到最后只剩下 1 个有序的序列。
现给定原始序列和由某排序算法产生的中间序列,请你判断该算法究竟是哪种排序算法?
输入格式:
输入在第一行给出正整数 n (≤100);随后一行给出原始序列的 n 个整数;最后一行给出由某排序算法产生的中间序列。这里假设排序的目标序列是升序。数字间以空格分隔。
输出格式:
首先在第 1 行中输出Insertion Sort表示插入排序、或Merge Sort表示归并排序;然后在第 2 行中输出用该排序算法再迭代一轮的结果序列。题目保证每组测试的结果是唯一的。数字间以空格分隔,且行首尾不得有多余空格。
输入样例 1:
10 3 1 2 8 7 5 9 4 6 0 1 2 3 7 8 5 9 4 6 0
输出样例 1:
Insertion Sort 1 2 3 5 7 8 9 4 6 0
输入样例 2:
10 3 1 2 8 7 5 9 4 0 6 1 3 2 8 5 7 4 9 0 6
输出样例 2:
Merge Sort 1 2 3 8 4 5 7 9 0 6
解析
#include <bits/stdc++.h> using namespace std;int main () { int n; cin >> n; vector<int > origin (n) , mid (n) , tmp (n) ; for (int i = 0 ; i < n; i++) cin >> origin[i]; for (int i = 0 ; i < n; i++) cin >> mid[i]; tmp = origin; bool isInsertion = false ; for (int i = 1 ; i < n; i++) { int key = tmp[i]; int j = i - 1 ; while (j >= 0 && tmp[j] > key) { tmp[j + 1 ] = tmp[j]; j--; } tmp[j + 1 ] = key; if (tmp == mid) { isInsertion = true ; i++; if (i < n) { key = tmp[i]; j = i - 1 ; while (j >= 0 && tmp[j] > key) { tmp[j + 1 ] = tmp[j]; j--; } tmp[j + 1 ] = key; } cout << "Insertion Sort\n" ; for (int k = 0 ; k < n; k++) { if (k) cout << " " ; cout << tmp[k]; } return 0 ; } } cout << "Merge Sort\n" ; tmp = origin; bool flag = false ; for (int step = 1 ; step < n; step *= 2 ) { vector<int > last = tmp; for (int i = 0 ; i < n; i += 2 * step) { int l = i; int midPos = min (i + step, n); int r = min (i + 2 * step, n); inplace_merge (tmp.begin () + l, tmp.begin () + midPos, tmp.begin () + r); } if (flag) { for (int k = 0 ; k < n; k++) { if (k) cout << " " ; cout << tmp[k]; } return 0 ; } if (tmp == mid) flag = true ; } return 0 ; }