第一期_排序及全排列题解

有些同学没学过c++,所以不想用c++,只想用c。

写c的第一个程序的也不见得各个语句什么意思都知道吧

在算法竞赛中用到的c++一般也就STL部分,其他可以按照c的写。

就是头文件变了,加了句using namespace std;

其他的c怎么写就怎么写就ok了

定义常量啥的习惯用#define就用#define呗

C++兼容C,C不兼容C++

//C
#include<stdio.h>
int main(){
	printf("hello world\n");
	return 0;
} 
//C++
#include<cstdio>
using namespace std;
int main(){
	printf("hello world\n");
	return 0;
}

7-1 分段排序 (10分)

在一个长度为10的数组中输入10个整数,把前5个数从小到大排序,后5个数从大到小排序。

输入格式:

输入10个整数。

输出格式:

排序后的数组,数与数间用空格分割。

输入样例:

5 9 2 4 6 7 1 3 0 8

输出样例:

2 4 5 6 9 8 7 3 1 0 
#include<cstdio>
#include<algorithm>
using namespace std;
int a[15];
bool cmp(int a,int b){
	return a>b;
}
int main(){
	for(int i=0;i<10;i++) scanf("%d",&a[i]);
	sort(a,a+5);
	sort(a+5,a+5+5,cmp);
	for(int i=0;i<10;i++) printf("%d ",a[i]);
	return 0;
} 

7-2 单词排序 (10分)

请编写程序,输入一系列单词,然后按字典顺序排序,最后输出结果。

输入格式

第一行为单词的数量 n (0<n<10000),后面有 n 行,每行一个英文单词(均由小写字母组成,且长度均不超过15个英文字母)

输出格式

共 n 行,每行一个英文单词(按字典顺序排列)

输入样例

3
stick
stock
stack

输出样例

stack
stick
stock
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e4+5;
struct node{
	char s[20];
}a[N];
bool cmp(node a,node b){
	return strcmp(a.s,b.s)<0;
}
int main(){
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%s",a[i].s);
	}
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++){
		printf("%s\n",a[i].s);
	}
	return 0;
} 

 

7-3 DKS学长和字符串 (15分)

我们可爱的dks学长特别喜欢字符串,就和他喜欢敲代码一样,可是我们的dks学长只喜欢英文字母(大写和小写),其他的字符他碰都不想碰,现在dks学长得到了若干个字符串,他想把这个字符串排序(区分大小写)。

排序的要求是按逆字典序排序(区分大小写),另外别忘了,可爱的dks学长只喜欢英文字母

输入格式:

第一行一个数字n ,代表有n组测试数据

接下来第2到第n+1行,每行会有一个字符串(只会出现大写和小写的英文字母以及数字,字符串长度小于10000位)

输出格式:

对应每个字符串,输出它按要求排序的结果

输入样例:

在这里给出一组输入。例如:

1
111dkstql111

输出样例:

在这里给出相应的输出。例如:

111tsqlkd111

 

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e4+5;
char s[N];
char ss[N];
bool cmp(char a,char b){
	return a>b;
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%s",s);
		int len=strlen(s);
		int top=0;
		for(int i=0;i<len;i++){
			if(s[i]>='0'&&s[i]<='9') continue;
			ss[top++]=s[i];
		}
		sort(ss,ss+top,cmp);
		int num=0;
		for(int i=0;i<len;i++){
			if(s[i]>='0'&&s[i]<='9') printf("%c",s[i]);
			else printf("%c",ss[num++]);	
		}
		printf("\n");
	}
	return 0;
}

7-4 身份证排序 (20分)

安全局搜索到了一批(n个)身份证号码,希望按出生日期对它们进行从大到小排序,如果有相同日期,则按身份证号码大小进行排序。身份证号码为18位的数字组成,出生日期为第7到第14位

输入格式:

第一行一个整数n,表示有n个身份证号码

余下的n行,每行一个身份证号码。

n<=100000

输出格式:

按出生日期从大到小排序后的身份证号,每行一条

输入样例:

在这里给出一组输入。例如:

5
466272307503271156
215856472207097978
234804580401078365
404475727700034980
710351408803093165

输出样例:

在这里给出相应的输出。例如:

404475727700034980
234804580401078365
215856472207097978
710351408803093165
466272307503271156

 

 

/*
这道题可以把身份证号看成数也可以看成字符串
注意 
pta的长整型是%lld
蓝桥的长整型是%I64d
*/ 
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=1e5+5;
struct node{
	ll ID;
	int br;
}a[N];
bool cmp(node a,node b){
	if(a.br!=b.br) return a.br>b.br;
	else return a.ID>b.ID;
}
int main(){
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i].ID);
		a[i].br=(a[i].ID/10000)%100000000;
	}
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++){
		printf("%lld\n",a[i].ID);
	}
	return 0;
}

 

7-5 模拟EXCEL排序 (25分)

Excel可以对一组纪录按任意指定列排序。现请编写程序实现类似功能。

输入格式:

输入的第一行包含两个正整数N(≤10​5​​) 和C,其中N是纪录的条数,C是指定排序的列号。之后有 N行,每行包含一条学生纪录。每条学生纪录由学号(6位数字,保证没有重复的学号)、姓名(不超过8位且不包含空格的字符串)、成绩([0, 100]内的整数)组成,相邻属性用1个空格隔开。

输出格式:

在N行中输出按要求排序后的结果,即:当C=1时,按学号递增排序;当C=2时,按姓名的非递减字典序排序;当C=3时,按成绩的非递减排序。当若干学生具有相同姓名或者相同成绩时,则按他们的学号递增排序。

输入样例:

3 1
000007 James 85
000010 Amy 90
000001 Zoe 60

输出样例:

000001 Zoe 60
000007 James 85
000010 Amy 90

 

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e5+5;
struct node{
	int ID;
	char name[15];
	int score;
}a[N];
bool cmp1(node a,node b){
	return a.ID<b.ID;
}
bool cmp2(node a,node b){
	if(strcmp(a.name,b.name))
	   return strcmp(a.name,b.name)<0;
	else
	   return a.ID<b.ID; 
}
bool cmp3(node a,node 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=1;i<=n;i++){
		scanf("%d%s%d",&a[i].ID,a[i].name,&a[i].score);
	}
	if(c==1) sort(a+1,a+1+n,cmp1);
	else if(c==2) sort(a+1,a+1+n,cmp2);
	else sort(a+1,a+1+n,cmp3);
	for(int i=1;i<=n;i++){
		printf("%06d %s %d\n",a[i].ID,a[i].name,a[i].score);
	}
	return 0;
}

7-6 输出全排列 (20分)

请编写程序输出前n个正整数的全排列(n<10),并通过9个测试用例(即n从1到9)观察n逐步增大时程序的运行时间。

输入格式:

输入给出正整数n(<10)。

输出格式:

输出1到n的全排列。每种排列占一行,数字间无空格。排列的输出顺序为字典序,即序列a​1​​,a​2​​,⋯,a​n​​排在序列b​1​​,b​2​​,⋯,b​n​​之前,如果存在k使得a​1​​=b​1​​,⋯,a​k​​=b​k​​ 并且 a​k+1​​<b​k+1​​。

输入样例:

3

输出样例:

123
132
213
231
312
321
#include<cstdio>
#include<algorithm>
using namespace std;
int a[15];
int main(){
	int n;
	scanf("%d",&n); 
	for(int i=1;i<=n;i++){
		a[i]=i;
	}
	do{
		for(int i=1;i<=n;i++) printf("%d",a[i]);
		printf("\n");
	}while(next_permutation(a+1,a+1+n));
	return 0;
} 

7-7 凑算式 (25分)

20180321224255533 .jpg

这个算式中A~I代表1~9的数字,不同的字母代表不同的数字。

比如: 6+8/3+952/714 就是一种解法, 5+3/1+972/486 是另一种解法。

这个算式一共有多少种解法?

输入格式:

无输入

输出格式:

前面若干行每一行输出一种解法,按ABCDEFGHI所代表的数的字典序从小到大输出

最后一行输出一共有多少种解法

输入样例:

无输入

输出样例:

……(表示若干种解法)
5+3/1+972/486
……(表示若干种解法)
6+8/3+952/714
……(表示若干种解法)
总的解法数

 

#include<cstdio>
#include<algorithm>
using namespace std;
int a[15]={1,2,3,4,5,6,7,8,9};
bool judge(){
	int A=a[0];
	int B=a[1];
	int C=a[2];
	int DEF=a[3]*100+a[4]*10+a[5];
	int GHI=a[6]*100+a[7]*10+a[8];
	if(A*C*GHI+B*GHI+DEF*C!=10*C*GHI) return false;
	printf("%d+%d/%d+%d/%d\n",A,B,C,DEF,GHI);
	return true;
}
int main(){
	int ans=0;
	do{
		if(judge()){
			ans++;
		}
	}while(next_permutation(a,a+9));
	printf("%d\n",ans);
	return 0;
}

 

7-8 六角填数 (25分)

如图所示六角形中,填入1~12的数字。

a.jpg

使得每条直线上的数字之和都相同。

图中,已经替你填好了3个数字,请你计算出每个位置的数是多少,按照abcdefghi的顺序输出?

输入格式:

输出格式:

按照abcdefghi的顺序输出每个位置的数,数与数之间用空格隔开,行末没有多余空格

输入样例:

在这里给出一组输入。例如:

输出样例:

在这里给出相应的输出。例如:

#include<cstdio>
#include<algorithm>
using namespace std;
int a[]={2,4,5,6,7,9,10,11,12};
bool judge(){
	int sum=8+a[0]+a[1]+a[2];
	if(sum!=1+a[0]+a[3]+a[5]) return false;
	if(sum!=1+a[1]+a[4]+a[8]) return false;
	if(sum!=8+a[3]+a[6]+3) return false;
	if(sum!=a[5]+a[6]+a[7]+a[8]) return false;
	if(sum!=a[2]+a[4]+a[7]+3) return false;
	return true;
}
int main(){
	do{
		if(judge()){
			for(int i=0;i<9;i++) 
			    printf("%d%c",a[i]," \n"[i==8]);
		}
	}while(next_permutation(a,a+9));
	return 0;
} 

 

 

7-9 名人堂与代金券 (25分)

对于在中国大学MOOC(http://www.icourse163.org/ )学习“数据结构”课程的学生,想要获得一张合格证书,总评成绩必须达到 60 分及以上,并且有另加福利:总评分在 [G, 100] 区间内者,可以得到 50 元 PAT 代金券;在 [60, G) 区间内者,可以得到 20 元PAT代金券。全国考点通用,一年有效。同时任课老师还会把总评成绩前 K 名的学生列入课程“名人堂”。本题就请你编写程序,帮助老师列出名人堂的学生,并统计一共发出了面值多少元的 PAT 代金券。

输入格式:

输入在第一行给出 3 个整数,分别是 N(不超过 10 000 的正整数,为学生总数)、G(在 (60,100) 区间内的整数,为题面中描述的代金券等级分界线)、K(不超过 100 且不超过 N 的正整数,为进入名人堂的最低名次)。接下来 N 行,每行给出一位学生的账号(长度不超过15位、不带空格的字符串)和总评成绩(区间 [0, 100] 内的整数),其间以空格分隔。题目保证没有重复的账号。

输出格式:

首先在一行中输出发出的 PAT 代金券的总面值。然后按总评成绩非升序输出进入名人堂的学生的名次、账号和成绩,其间以 1 个空格分隔。需要注意的是:成绩相同的学生享有并列的排名,排名并列时,按账号的字母序升序输出。

输入样例:

10 80 5
cy@zju.edu.cn 78
cy@pat-edu.com 87
1001@qq.com 65
uh-oh@163.com 96
test@126.com 39
anyone@qq.com 87
zoe@mit.edu 80
jack@ucla.edu 88
bob@cmu.edu 80
ken@163.com 70

输出样例:

360
1 uh-oh@163.com 96
2 jack@ucla.edu 88
3 anyone@qq.com 87
3 cy@pat-edu.com 87
5 bob@cmu.edu 80
5 zoe@mit.edu 80
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct node{
	char ID[20];
	int score;
	int rk;//排名 
}a[10005];
bool cmp(node a,node b){
	if(a.score!=b.score) return a.score>b.score;
	else return strcmp(a.ID,b.ID)<0;
} 
int main(){
	int n,G,K;
	int sum=0;
	scanf("%d%d%d",&n,&G,&K);
	for(int i=1;i<=n;i++){
		scanf("%s%d",a[i].ID,&a[i].score);
		if(a[i].score>=G) sum+=50;
		else if(a[i].score>=60&&a[i].score<G) sum+=20;
	}
	printf("%d\n",sum);
	sort(a+1,a+1+n,cmp);
	int ls=0x3f3f3f3f;//初始化上一个分数为无穷大 (本题中只要比100大就行) 
	int lr=0;
	for(int i=1;i<=n;i++){
		if(a[i].score==ls) a[i].rk=lr;
		else{
			a[i].rk=i;
			ls=a[i].score;
			lr=i;
		}
		if(a[i].rk>K) break;
		else printf("%d %s %d\n",a[i].rk,a[i].ID,a[i].score); 
	}
	return 0;
}

7-10 PAT排名汇总 (25分)

计算机程序设计能力考试(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
1234567890003 95
1234567890002 77
1234567890004 85
4
1234567890013 65
1234567890011 25
1234567890014 100
1234567890012 85

输出样例:

9
1234567890005 1 1 1
1234567890014 1 2 1
1234567890001 3 1 2
1234567890003 3 1 2
1234567890004 5 1 4
1234567890012 5 2 2
1234567890002 7 1 5
1234567890013 8 2 3
1234567890011 9 2 4
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
struct node{
	ll ID;//考号 
	int frk;//最终排名 
	int num;//考点编号
	int rk;//在该考点的排名 
	int score;
}a[30005];
bool cmp(node a,node b){
	if(a.score!=b.score) return a.score>b.score;
	else return a.ID<b.ID;
}
int ls[105],lr[105],cnt[105];
//ls[i]代表第i考场上一个人的成绩,lr[i]代表第i考场上一个人的排名
//ls[0]表示总的上一个人的成绩,rs[0]表示总的上一个人的排名 
int main(){
	int n;
	scanf("%d",&n);
	int size=0; 
	for(int k=1;k<=n;k++){
		int m;
		scanf("%d",&m);
		for(int i=1;i<=m;i++){		
		    size++;
			scanf("%lld%d",&a[size].ID,&a[size].score);
			a[size].num=k;
			
		}
	}
	sort(a+1,a+1+size,cmp);
	printf("%d\n",size);
	for(int i=0;i<=n;i++){
		ls[i]=0x3f3f3f3f;
		lr[i]=0;
		cnt[i]=0;
	}
	for(int i=1;i<=size;i++){
		if(a[i].score==ls[0]) a[i].frk=lr[0];
		else{
			a[i].frk=i;
			ls[0]=a[i].score;
			lr[0]=i;
		}
		int id=a[i].num;//所在考场编号
		cnt[id]++;
		if(a[i].score==ls[id]) a[i].rk=lr[id];
		else{
			a[i].rk=cnt[id];
			ls[id]=a[i].score;
			lr[id]=cnt[id];
		} 
	} 
	for(int i=1;i<=size;i++){
		printf("%013lld %d %d %d\n",a[i].ID,a[i].frk,a[i].num,a[i].rk);
	}
	return 0;
}

 

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值