题目描述
某城镇进行人口普查,得到了全体居民的生日。现请你写个程序,找出镇上最年长和最年轻的人。
这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过 200 岁的老人,而今天是 2014 年 9 月 6 日,所以超过 200 岁的生日和未出生的生日都是不合理的,应该被过滤掉。
输入格式:
输入在第一行给出正整数 N,取值在(0,105];随后 N 行,每行给出 1 个人的姓名(由不超过 5 个英文字母组成的字符串)、以及按 yyyy/mm/dd
(即年/月/日)格式给出的生日。题目保证最年长和最年轻的人没有并列。
输出格式:
在一行中顺序输出有效生日的个数、最年长人和最年轻人的姓名,其间以空格分隔。
输入样例:
1 | 5 |
输出样例:
1 | 3 Tom John |
当没有合法生日时,要输出0
解答
我的代码没有通过PTA最后一个测试点,但是却能在牛客网AC。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//判断是否是闰年
int isp(int y)
{
if(y%400==0||y%4==0&&y%100!=0)
return 1;
else
return 0;
}
//给定某人出生日期,计算其总共存活天数day
int allday(int y,int m,int d)
{
int month[12]={31,28,31,30,31,30,31,31,30,31,30,31};
//计算出生那一年所占的天数byd
int byd=0;
for(int j=y+1;j<=12;++j)
{
byd+=month[j-1];
}
int day=byd+month[m-1]-d;
if(m<=2&&isp(y))
day+=1;//闰年则加1
//计算从出生第二年至2014年1月1号之间的天数
for(int k=y+1;k<2014;++k)
{
day+=365;
if(isp(k))
day+=1;//闰年则加1
}
//计算2014年1月1号2014年9月6日之间的天数
for(int p=1;p<=8;++p)
{
day+=month[p-1];
}
if(isp(2014))
day+=1;//闰年则加1
day+=6;//这便是总共的生存天数
return day;
}
int main()
{
int n;//给定的人数
char name[6];//名字
int y,m,d;//出生年月日
scanf("%d",&n);
getchar();
int cnt=0;//合法的生日个数
int day=0;//总共存活天数
int th=allday(1814,9,6);//计算两百岁的人所存活的总天数th
//printf("200岁共%d天\n\n",th);
char maxname[6],minname[6];//记录年龄最大和年龄最小的人的姓名
int maxday=0,minday=th+1;//初始化年龄最大和最小的人的总共存活天数
for(int i=0;i<n;++i)
{
scanf("%s %d/%d/%d",name,&y,&m,&d);
//printf("m=%d d=%d\n",m,d);
day=allday(y,m,d);//计算这个人的总共存活天数
//printf("%s:%d\n",name,day);
//合法性判断
if(day>th)//年龄超过200岁
{
//printf("%s超过200岁了\n",name);
continue;
}
if(y>2014||(y==2014)&&(m>9)||(y==2014)&&(m==9)&&(d>6))//此人还未出生
{
//printf("%s 还未出生\n",name);
continue;
}
//此时合法,继续下面的操作
++cnt;
if(day>maxday)
{
maxday=day;
strcpy(maxname,name);
}
if(day<minday)
{
minday=day;
strcpy(minname,name);
}
}
if(cnt==0)
printf("0");
else
printf("%d %s %s",cnt,maxname,minname);
}网上的做法大部分都是将生日转化为数字来做的,不用像我那样考虑的那么复杂
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
int solve(int year,int month,int day);
int main( )
{
int year,month,day;
int n,i,count=0;
int min_age=18140905,max_age=20140907;//初始化时稍微大过范围即可
char name[8],max_name[8],min_name[8];
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%s%d/%d/%d",name,&year,&month,&day);
int k=solve(year,month,day);
if(k>0)//年龄在范围内
{
if(max_age>k)//年龄越大,日期越小
{
max_age=k;
strcpy(max_name,name);//字符串复制
}
if(min_age<k)//年龄越小,日期越大
{
min_age=k;
strcpy(min_name,name);
}
count++;
}
}
//当合法生日为0时,只输出0,测试点3
if(count)
printf("%d %s %s",count,max_name,min_name);
else
printf("0");
return 0;
}
int solve(int year,int month,int day)
{
//因为题目说明,输入的日期一定合理,所以可以这样算
int e=year*10000+month*100+day;
if(e>20140906||e<18140906)
return -1;
return e;
}也可以这样
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
int number(int y, int m, int d)
{
return y*10000 + m*100 + d;
}
int main()
{
char temp[10], name_max[10], name_min[10];
int y, m, d, n, count=0, x;
int max = 18140906, min = 120140906;
scanf("%d", &n);
for(int i=0; i<n; ++i){
scanf("%s %d/%d/%d", temp, &y, &m, &d);
x = number(y, m, d);
if(x >= 18140906 && x <= 20140906){
count++;
if(x > max){
max = x;
strcpy(name_max, temp);
}
if(x < min){
min = x;
strcpy(name_min, temp);
}
}
}
if(count == 0)
printf("0");
else{
printf("%d %s %s", count,name_min, name_max );
}
return 0;
}