PAT B1028. 人口普查 (20)

1028 人口普查 (20 分)

某城镇进行人口普查,得到了全体居民的生日。现请你写个程序,找出镇上最年长和最年轻的人。

这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过 200 岁的老人,而今天是 2014 年 9 月 6 日,所以超过 200 岁的生日和未出生的生日都是不合理的,应该被过滤掉。

输入格式:
输入在第一行给出正整数 N,取值在(0,10^​5​​ ];随后 N 行,每行给出 1 个人的姓名(由不超过 5 个英文字母组成的字符串)、以及按 yyyy/mm/dd(即年/月/日)格式给出的生日。题目保证最年长和最年轻的人没有并列。

输出格式:
在一行中顺序输出有效生日的个数、最年长人和最年轻人的姓名,其间以空格分隔。

输入样例:
5
John 2001/05/12
Tom 1814/09/06
Ann 2121/01/30
James 1814/09/05
Steve 1967/11/20
输出样例:
3 Tom John

思路1:

int型变量N存放人数,string型数组num存放输入的名字及生日,int型数组num1存放num数组中空格的位置,int型变量count记录有效生日个数,count_max,count_min记录最晚生日和最早生日的编号,max和min记录最晚生日和最早生日日期。
第一个for循环将输入存放至num数组,第二个for循环将找到num数组中每个元素中空格的位置,并存入num1数组(为了确定名字长度),第三个for循环删去num数组中字符串的空格和‘/’,第四个for循环用以确定有效生日,最晚生日及最早生日。最后按格式输出。

参考代码1:

#include <iostream>
#include <string>
using namespace std;
int main(){
	int N;
	scanf("%d",&N);
	string num[100010];	
	for(int i=0;i<=N;i++){//存储输入; 
		getline(cin,num[i]);
	}
	
	int num1[100010];
	for(int i=1;i<=N;i++){
		num1[i]=num[i].find(" ");
	}
	for(int i=1;i<=N;i++){//删去空格和/ 
		num[i].erase(num1[i],1);
		num[i].erase(num1[i]+4,1);
		num[i].erase(num1[i]+6,1);
	}
	int count=0,count_min=0,count_max=0,max=18140906,min=20140906;
	for(int i=0;i<=N;i++){
		string str=num[i].substr(num1[i],8);
		int num2=atoi(str.c_str());//atoi()l里面只能传递const char类型,需将string转化为从上图char 
		if(num2>=18140906&&num2<=20140906) {
			if(num2>max) {
				max=num2;count_min=i;
			}
			if(num2<min) {
				min=num2;count_max=i;
			}
			count++;
		}		
	}
	if(count==0) printf("0");
	else{
		printf("%d ",count);
		for(int i=0;i<num1[count_max];i++){
			printf("%c",num[count_max][i]);
		}
		printf(" ");
		for(int i=0;i<num1[count_min];i++){
			printf("%c",num[count_min][i]);
		}
	}
	return 0;
} 

思路2:

定义结构体person用以存储每个人的姓名及生日,lessequ和moreequ函数用来判断两个人的生日是大还是小,init函数用来初始化有效生日边界以便判断某人生日是否合法。
main函数中int型变量存放人数,num存放有效生日个数,temp临时存放某人的姓名和生日,oldest和youngest存放最年长和最年轻人的姓名和生日。
for循环中接收输入,进行有效性判断,进行最大值最小值判断,都依靠moreequ,lessequ函数。
最后按格式进行输出。

参考代码2:

#include <cstdio>
struct person {
	char name[10];
	int yy,mm,dd;//日期; 
}oldest,youngest,left,right,temp;
//oldest,youngest 存放最年老的和最年起的人,left和right存放合法日期边界;
bool lessequ(person a,person b){//如果a的日期小于等于b,则返回true; 
	if(a.yy!=b.yy) return a.yy<=b.yy;
	else if(a.mm!=b.mm) return a.mm<=b.mm;
	else return a.dd<=b.dd;
}
bool moreequ(person a,person b){//如果a的日期大于等于b,则返回true; 
	if(a.yy!=b.yy) return a.yy>=b.yy;
	else if(a.mm!=b.mm) return a.mm>=b.mm;
	else return a.dd>=b.dd;
} 
void init (){
	youngest.yy=left.yy=1814;
	oldest.yy=right.yy=2014;
	youngest.mm=oldest.mm=left.mm=right.mm=9;
	youngest.dd=oldest.dd=left.dd=right.dd=6;
} 
int main(){
	init();//初始化;
	int n, num=0;//统计存放合法日期的人数
	scanf("%d",&n);
	for (int i=0;i<n;i++){
		scanf("%s %d/%d/%d",&temp.name,&temp.yy,&temp.mm,&temp.dd);
		if(moreequ(temp,left)&&lessequ(temp,right)){
			num++;
			if(lessequ(temp,oldest)) oldest =temp;//更新oldest;
			if(moreequ(temp,youngest)) youngest=temp;//更新youngest 
		}
	} 
	if(num==0) printf("0\n");
	else printf("%d %s %s\n",num,oldest.name,youngest.name);
	return 0; 
}

点评:

①此题属于查找元素型,将数据输入数组中,按题目要求进行查找输出即可。
②思路1采用了字符串数组的方式,用getline进行字符串输入,string.find()用来查找空格位置,string.erase()用来删除空格和/,string.substr()用来截取字符串的子串,atoi(char)用来把char类型转化成int型,提取出日期的整数再进行生日的一系列判断就简单多了。
③思路2采用常规定义struct的做法,oldest,youngest,left,right,temp分别存放最年老,最年轻,最早,最晚,以及临时的某个人信息。利用lessequ和moreque函数就可以统计有效生日和计算出最年老最年轻的人。思路2应作为模板记住并熟练使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值