PAT《算法笔记》入门篇(2)算法初步-排序散列递归贪心二分等

排序

A1025

问题:
思路:
关键:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int N,K;
const int maxn = 30010;
struct stu{
   
	char id[15];
	int score,final_rank,local_number,local_rank;
};
stu a[maxn];
bool cmp(stu a,stu b){
   
	if(a.score!=b.score) return a.score>b.score;
	else	return strcmp(a.id,b.id)<0; 
}
int num = 0;
int main(){
   
	scanf("%d",&N);
	for(int i=1;i<=N;i++){
   
		scanf("%d",&K);
		for(int j=0;j<K;j++){
   
			scanf("%s %d",a[num].id,&a[num].score);
			a[num].local_number = i;
			num++;
		}
		sort(a+num-K,a+num,cmp);
		a[num-K].local_rank = 1;
		for(int j=1;j<K;j++){
   
			if(a[num-K+j].score==a[num-K+j-1].score)
				a[num-K+j].local_rank = a[num-K+j-1].local_rank;
			else{
   
				a[num-K+j].local_rank = j+1;
			}
		}
	}
	sort(a,a+num,cmp);
	a[0].final_rank = 1;
	for(int j=1;j<num;j++){
   
		if(a[j].score==a[j-1].score)
			a[j].final_rank = a[j-1].final_rank;
		else{
   
			a[j].final_rank = j+1;
		}
	}
	printf("%d\n",num);
	for(int i=0;i<num;i++){
   
		printf("%s %d %d %d\n",a[i].id,a[i].final_rank,a[i].local_number,a[i].local_rank);
	}
	return 0;
}

A1062

问题:
思路:对于圣人、君子等可以在结构体中用一个level来区分
关键:
1.注意题目给出的范围,比如 10 5 {10}^5 105后面5个0 !

#include<cstdio>
#include<algorithm>
using namespace std;
int N,L,H,M=0;
struct people{
   
	int id,v,t;
	int total;
	int level;
};
people a[100010];
bool cmp(people a,people b){
   
	if(a.level!=b.level)
		return a.level>b.level;
	else{
   
		if(a.total!=b.total)
			return a.total>b.total;
		else{
   
			if(a.v!=b.v)
				return a.v>b.v;
			else{
   
				return a.id < b.id;
			}
		}
	}
}
int main(){
   
	scanf("%d %d %d",&N,&L,&H);
	int num = 0;
	for(int i=0,id,v,t;i<N;i++){
   
		scanf("%d %d %d",&id,&v,&t);
		if(v>=L&&t>=L){
   
			a[num].id = id;
			a[num].v = v;
			a[num].t = t;
			a[num].total = v + t;
			if(v>=H&&t>=H)
				a[num].level = 4;
			else if(v>=H&&t<H)
				a[num].level = 3;
			else if(v<=H&&t<=H&&v>=t)
				a[num].level = 2;
			else
				a[num].level = 1;
			num++;
		}
	}
	sort(a,a+num,cmp);
	printf("%d\n",num);
	for(int i=0;i<num;i++){
   
		printf("%d %d %d\n",a[i].id,a[i].v,a[i].t);
	}
}

A1012【review | 主要看这里默认的一些规则】

默认规则:

对于分数相同的排名应该是 1 1 3 4 5,而不是1 1 2 3 4
平均分是四舍五入的,所以需要按照+0.5后取整,保证是四舍五入

ac代码:

#include<iostream>
#include<map>
#include<algorithm>
#include<set>
using namespace std;
const int maxn = 2010;
struct stu{
   
	string id;
	int g;
};
int N,M;
stu a[4][maxn];
bool cmp(stu x, stu y){
   
	return x.g > y.g;
}
map<string,bool> book;
char lesson[4] = {
   'A','C','M','E'};
int main(){
   
	string str;
	cin >> N >> M;
	for(int i=0;i<N;i++){
   
		cin >> str;
		book[str]=true;
		double sum = 0;
		for(int j=1;j<=3;j++){
   
			a[j][i].id = str;
			cin >> a[j][i].g;
			sum += a[j][i].g;
		}
		a[0][i].id = str;
		//考虑四舍五入 
		a[0][i].g = (int)(sum/3+0.5);
	}
	for(int i=0;i<4;i++){
   
		sort(a[i],a[i]+N,cmp);
	}
	for(int i=0;i<M;i++){
   
		cin >> str;
		if(!book[str]){
   
			printf("N/A\n");
			continue;
		}
		int best_rank = N+1;
		int best_lesson = 0;
		for(int j=0;j<4;j++){
   
			int rank = 1;
			for(int k=0;k<N;k++){
   
				//还要考虑排名并列的情况
				//是 1 1 3 4 5这种,而不是1 1 2 3 4 
				if(k!=0&&a[j][k].g!=a[j][k-1].g)
					rank = k+1;
				if(a[j][k].id==str&&best_rank>rank){
   
					best_rank = rank;
					best_lesson = j;
					break;
				}
			}
		}
		printf("%d ",best_rank);
		printf("%c\n",lesson[best_lesson]);
	}
	return 0;
}

A1016【好麻烦 有空做】

A1028

问题:
思路:写三个cmp
关键:
1.注意排序方向

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

A1055

问题:
思路:
关键:
1.如果采用对每个查询都时重新按年龄排一次序,或者在每次查询时都进行一次数组的复制,都会导致超时。

int a[] = {
   'a','b','c'};
int b[10];
copy(a,a+3,b);//将a[0]~a[2]从b[0]开始复制给b

2.首先对整个数组进行排序,然后每次查询对源数组以age为条件遍历一遍的方式,能ac

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int N,K;
struct people{
   
	char name[10];
	int age,w;
};
people a[100010];
bool cmp(people a,people b){
   
	return a.age<b.age;
}
bool cmp1(people a,people b){
   
	if(a.w!=b.w){
   
		return a.w>b.w;
	}else{
   
		if(a.age!=b.age){
   
			return a.age<b.age;
		}else{
   
			return strcmp(a.name,b.name)<0;
		}
	}
}
int main(){
   
//	freopen("1.txt","r",stdin);
	scanf("%d %d",&N,&K);
	for(int i=0;i<N;i++){
   
		scanf("%s %d %d",a[i].name,&a[i].age,&a[i].w);
	}
	sort(a,a+N,cmp1);
	int topK,L,H;
	for(int i=1;i<=K;i++){
   
		int printNum=0;
		printf("Case #%d:\n",i);
		scanf("%d %d %d",&topK,&L,&H);
		for(int j=0;j<N&&printNum<topK;j++){
   
			if(a[j].age>=L&&a[j].age<=H){
   
				printf("%s %d %d\n",a[j].name,a[j].age,a[j].w);
				printNum++;
			}
		}
        if(printNum==0)printf("None\n");
	}
}

3.考虑到查询数不超过100,因此可以取每个年龄段的前100人(后100人显然没有机会,反证法)组成一个规模较小的数组用来查询。能ac且效率更高。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int N,K;
struct people{
   
	char name[10];
	int age,w;
};
people a[100010];
people b[100010];
int bNum=0;
int age[210]={
   0};
bool cmp(people a,people b){
   
	return a.age<b.age;
}
bool cmp1(people a,people b){
   
	if(a.w!=b.w){
   
		return a.w>b.w;
	}else{
   
		if(a
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值