[PAT Basic Level] 1090~1095

1090. 危险品装箱

题目分析:

这里有一个问题需要好好注意,从给的样例可以看到,可能一个物品与2种不同的物品都会配对成为危险品,所以这里比较好的策略是开一个比较大的数组,以下标表示物品编号,储存的值表示配对的危险品编号,例如:20005与20001是危险品,20006,20005构成危险品,则Arr[2005]=20001,Arr[20006]=20005。

源代码

#include <cstdio>

int main()
{
	int unpairNum,listNum;
	scanf("%d %d",&unpairNum,&listNum);
	int *danList,*goodsList;
	danList=new int [100000];
	goodsList=new int[100000];
	for(int i=0;i<100000;++i) danList[i]=goodsList[i]=0;
	int dangeID1,dangeID2;
	for(int i=0;i<unpairNum;++i){
		scanf("%d %d",&dangeID1,&dangeID2);
		if(danList[dangeID1]==0)
			danList[dangeID1]=dangeID2;
		else danList[dangeID2]=dangeID1;
	}
	bool Is_safe;
	for(int i=0;i<listNum;++i){
		int num;
		scanf("%d",&num);
		int *tmp=new int[num];
		for(int i=0;i<num;++i){
			scanf("%d",&tmp[i]);
			goodsList[tmp[i]]=1;
		}
		Is_safe=true;
		for(int i=0;i<num;++i)
			if(danList[tmp[i]]&&goodsList[danList[tmp[i]]]){ //如果此物品出现在危险品列表且不相容物品也在清单中 
				Is_safe=false;
				break; 
			}
		if(Is_safe) printf("Yes\n");
		else printf("No\n");
		for(int i=0;i<num;++i)
			goodsList[tmp[i]]=0;  //重置回0 
		delete []tmp; //释放空间 
	}
	delete []danList;
	delete []goodsList;
	return 0; 
}

1091. N-自守数

题目分析:

这题比较容易,从1开始遍历,依次寻找如果满足要求那就立即输出。

源代码

#include <cstdio>

int main()
{
	int num;
	scanf("%d",&num);
	while(num--){
		int count=0; //统计数字位数
		int value,copy;
		scanf("%d",&value);
		copy=value;
		while(copy){
			copy/=10;
			count++;
		}
		bool find=false;
		for(int i=1;i<10;++i){ //N最大9 
			int mul=value*value*i;
			copy=value;
			for(int j=0;j<count;++j){
				if(mul%10!=copy%10) break;
				mul/=10; copy/=10;
			}
			if(copy==0){ //说明末尾几位恰为K
				find=true;
				printf("%d %d\n",i,value*value*i); 
				break;
			}
		}
		if(!find) printf("No\n"); 
	} 
	return 0;
}

1092. 最好吃的月饼

题目分析:

根据输入依次累加求出各类月饼的总销量,然后遍历一遍找出销量最高值max,再遍历一遍,将所有销量为max的月饼编号输出即可。

源代码

#include <cstdio>

int main()
{
	int kinds,cityNum,sell;
	scanf("%d %d",&kinds,&cityNum);
	int *sum=new int[kinds];
	for(int i=0;i<kinds;++i)
		sum[i]=0;
	while(cityNum--){
		for(int i=0;i<kinds;++i){
			scanf("%d",&sell);
			sum[i]+=sell;
		}
	}
	int max=-1;
	for(int i=0;i<kinds;++i)
		if(max<sum[i]) max=sum[i];
	printf("%d\n",max);
	int first=0;
	for(int i=0;i<kinds;++i)
		if(sum[i]==max){
			if(first) printf(" ");
			first++;
			printf("%d",i+1);
		}
	delete []sum;
	return 0;
}

1093. 字符串A+B

题目分析:

首先用一个大小为128的int数组来记录各个字符是否出现,出现记为1,否则记为0。然后输出时,从第一个字符开始,查询下标为该字符对应的ASCII码的元素是否为1,为1则输出并将其修改为0,否则不输出,这样就可以保证所有相同字符出现且仅出现一次。

源代码

#include <iostream>
#include <string>

int main()
{
	using namespace std;
	int exist[128];
	for(int i=0;i<128;++i) exist[i]=0;
	string sA,sB;
	getline(cin,sA);
	getline(cin,sB);
	int lenA=sA.size(),lenB=sB.size();
	for(int i=0;i<lenA;++i)
		exist[sA[i]]=1;
	for(int i=0;i<lenB;++i)
		exist[sB[i]]=1;
	for(int i=0;i<lenA;++i)
		if(exist[sA[i]]){
			exist[sA[i]]=0;
			putchar(sA[i]);
		}
	
	for(int i=0;i<lenB;++i)
		if(exist[sB[i]]){
			exist[sB[i]]=0;
			putchar(sB[i]);
		}
	return 0;
}

1094. 谷歌的招聘

题目分析:

核心思想还是判定素数,不过这里需要将字符串转化成数字来进行计算,可以用stoi()这个函数,作用是将一个const string对象转化成对应的十进制数,也可以用atoi(),不过它的参数是const char*,如果是string对象的话需要用c_str()函数创建一个const char*再用atoi()。不过这两个函数可能在Dev C++5.10上使用不了,我测试过编译不了,但g++可以顺利编译运行。

源代码

/******注:这里用到的stoi()函数在Dev C++5.10版本中无法编译,VS2017中可以顺利编译*******/
#include <iostream>
#include <cmath>
#include <cstring>
#include <string>

bool isPrim(int num) {
	if (num == 2 || num == 3) return true;
	if (num % 6 == 1 || num % 6 == 5) {
		int i, gap = 4, limit = sqrt((double)num);
		for (i = 5; i <= limit; i += gap) {
			if (num%i == 0) return false;
			if (gap == 2) gap = 4;
			else gap = 2;
		}
		return true;
	}
	return false;
}
int main()
{
	using namespace std;
	int len, key; //数字长度以及K 
	string number;
	cin >> len >> key >> number;
	bool findPrim = false;
	for (int i = key - 1; i < len; ++i) {
		int value;
		string tmp = number.substr(i - key + 1, key);
		value = stoi(tmp);
		if (isPrim(value)) {
			findPrim = true;
			cout << tmp;
			break;
		}
	}
	if (!findPrim) printf("404");
	return 0;
}

1095. 解码PAT准考证

题目分析:

真是让我痛苦非常的一道题,大概也是编写的最久的一道题,由于现在对STL不熟悉,写起来真的非常,非常麻烦,不过好在他是最后一道题,刷完这道就乙级通关了~
由于实在是比较长,很多细节,直接放上了代码,网上有一些写的很好的代码很简单,柳婼的博客上有一篇代码,47行很简洁,这里放上链接,大家还是移步去看看别人写的优秀代码来的好,希望自己也早日提升水平,写出简洁优美的代码。
https://blog.csdn.net/liuchuo/article/details/84972869

源代码

//2020.03.26 

#include <cstdio>
#include <algorithm>
#include <cstring>

struct candiInfo{
	char id[14]; //准考证号 
	int score; 
};
struct testRoom{
	int number=0; //考场人数 
	int id;     //id 
};
bool cmp1(const candiInfo& c1,const candiInfo& c2){  //按类型1排序
	if(c1.id[0]!=c2.id[0]) return c1.id[0]<c2.id[0];  //按类型字母排序,依次A B T 
	if(c1.score!=c2.score) return c1.score>c2.score;  //按分数非升序排列
	return strcmp(c1.id,c2.id)<0;  //按准考证字典升序输出 
}
bool cmp2(const candiInfo& c1,const candiInfo& c2){  //按类型3排列 
	char date1[7],date2[7];
	strncpy(date1,&c1.id[4],6); date1[6]='\0';
	strncpy(date2,&c2.id[4],6); date2[6]='\0';
	int compare=strcmp(date1,date2); 
	if(compare!=0) return compare<0;  //按日期升序排列
	int examRoom1,examRoom2;
	examRoom1=(c1.id[1]-'0')*100+(c1.id[2]-'0')*10+c1.id[3]-'0'; 
	examRoom2=(c2.id[1]-'0')*100+(c2.id[2]-'0')*10+c2.id[3]-'0';
	return examRoom1<examRoom2; //按考场升序排列 
}
bool cmp3(const testRoom&t1,const testRoom& t2){
	if(t1.number!=t2.number) return t1.number>t2.number;
	return t1.id<t2.id;
}
int main()
{
	int candiNum,quryNum;
	scanf("%d %d",&candiNum,&quryNum);
	candiInfo* candiList1=new candiInfo[candiNum];
	candiInfo* candiList2=new candiInfo [candiNum];
	int room[1000][2]={0};
	for(int i=0;i<candiNum;++i){
		scanf("%s %d",candiList1[i].id,&candiList1[i].score);
		candiList2[i]=candiList1[i];
		int examroom=(candiList1[i].id[1]-'0')*100+(candiList1[i].id[2]-'0')*10+candiList1[i].id[3]-'0';
		room[examroom][0]++; //人数+1;
		room[examroom][1]+=candiList1[i].score;  //计算该考场总分 
	}	 
	std::sort(candiList1,candiList1+candiNum,cmp1);
	std::sort(candiList2,candiList2+candiNum,cmp2);
	int caseID;
	int order=0;
	while(quryNum--){
		order++;
		scanf("%d",&caseID);
		getchar();  //读取空格 
		switch(caseID){
			case 1:{
				char type=getchar();
				int j;
				for(j=0;j<candiNum&&candiList1[j].id[0]!=type;++j); //找到符合要求可输出的位置
				printf("Case %d: 1 %c\n",order,type);
				if(j==candiNum) {printf("NA\n");break; }
				while(j<candiNum&&candiList1[j].id[0]==type) {
					printf("%s %d\n",candiList1[j].id,candiList1[j].score);
					j++;
				}
				break; 
			}
			case 2:{
				int roomid;
				scanf("%d",&roomid);
				printf("Case %d: 2 %d\n",order,roomid);
				if(room[roomid][0]==0) {printf("NA\n");break;}
				printf("%d %d\n",room[roomid][0],room[roomid][1]);
				break;
			}
			case 3:{ 
				char date[7];
				char tmp[7];
				tmp[6]='\0';
				scanf("%s",date);
				int begin=-1,end;
				for(int j=0;j<candiNum;++j){
					strncpy(tmp,&candiList2[j].id[4],6);
					if(strcmp(tmp,date)==0){
						if(begin<0) begin=j;
						end=j;
					}
				}
				int count=1; //统计有几个不同考场 
				printf("Case %d: 3 %s\n",order,date);
				if(begin<0) {printf("NA\n");break;}
				int pre=(candiList2[begin].id[1]-'0')*100+(candiList2[begin].id[2]-'0')*10+candiList2[begin].id[3]-'0';
				int cur;
				for(int i=begin+1;i<=end;++i){
					cur=(candiList2[i].id[1]-'0')*100+(candiList2[i].id[2]-'0')*10+candiList2[i].id[3]-'0';
					if(cur!=pre){ pre=cur;count++;}
				} 
				testRoom *show=new testRoom[count];
				pre=pre=(candiList2[begin].id[1]-'0')*100+(candiList2[begin].id[2]-'0')*10+candiList2[begin].id[3]-'0';
				int temp=0;
				show[temp].id=pre;
				show[temp].number++;
				for(int i=begin+1;i<=end;++i){
					cur=(candiList2[i].id[1]-'0')*100+(candiList2[i].id[2]-'0')*10+candiList2[i].id[3]-'0';
					if(cur!=pre){
						show[++temp].id=cur;
						show[temp].number++;
						pre=cur;
					}
					else show[temp].number++;	
				}
				std::sort(show,show+count,cmp3);
				for(int i=0;i<count;++i)
					printf("%d %d\n",show[i].id,show[i].number);
				delete []show;
				break;
			}
			default: break;
		}
	}
	delete []candiList1;
	delete []candiList2;
	return 0;
}

写到这里,历时将近一个月,我的PAT乙级95道题终于全部刷完了,见识到了别人的代码与自己代码的差距,也学到了不少东西。也很高兴自己能按自己的想法和计划把它做下来,也祝愿未来的自己以及所有奋战苦练的人,都能够坚持自己的初心,一步一步地把自己的目标实现下来。乙级也还只是一个开始,甲级要继续冲了嗷!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值