化繁就简(结构体在算法中的运用)
题目
某城镇进行人口普查,得到了全体居民的生日。现请你写个程序,找出镇上最年长和最年轻的人。
这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过200岁的老人,而今天是2014年9月6日,所以超过200
岁的生日和未出生的生日都是不合理的,应该被过滤掉。
输入描述:
输入在第一行给出正整数N,取值在(0, 105];随后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
*/
我的算法
#include <stdio.h>
#include <string.h>
int main(void)
{
int n, cnt = 0;
int y, m, d;
int t, flag = 1, flag2 = 0;
int i, j, k;
int mi, mj, mk, ni, nj, nk;
char name1[10], name2[10];
char name[10];
scanf ("%d", &n);
t = n;
getchar ();
while (t--)
{
scanf (" %s %d/%d/%d", name, &y, &m, &d);
if ((1814 <= y && y <= 2014))
{
if (y == 2014)
{
if (m <= 9 && d <= 6)
{
cnt++;
flag2 = 1;
}
}
else if (y == 1814)
{
if (y >= 9 && d >= 6)
{
cnt++;
flag2 = 1;
}
}
else
{
cnt++;
flag2 = 1;
}
if (flag && flag2)
{
strcpy (name1, name);
mi = 2014 - y;
mj = m - 9;
mk = d - 6;
strcpy (name2, name);
ni = 2014 - y;
nj = m - 9;
nk = d - 6;
flag = 0;
}
if (flag == 0)
{
i = 2014 - y;
j = m - 9;
k = d - 6;
if (i >= mi)
{
if (i == mi)
{
if (j >= mj)
{
if (j == mj)
{
if (k > mk)
{
strcpy (name1, name);
mi = i;
mj = j;
mk = k;
}
}
else
{
strcpy (name1, name);
mi = i;
mj = j;
mk = k;
}
}
}
else
{
strcpy (name1, name);
mi = i;
mj = j;
mk = k;
}
}
if (i <= ni)
{
if (i == ni)
{
if (j <= nj)
{
if (j == nj)
{
if (k < nk)
{
strcpy (name2, name);
ni = i;
nj = j;
nk = k;
}
}
else
{
strcpy (name2, name);
ni = i;
nj = j;
nk = k;
}
}
}
else
{
strcpy (name2, name);
ni = i;
nj = j;
nk = k;
}
}
}
}
}
printf ("%d ", cnt);
for (i = 0; name1[i] != '\0'; i++)
{
putchar (name1[i]);
}
putchar (' ');
for (i = 0; name2[i] != '\0'; i++)
{
putchar (name2[i]);
}
return 0;
}
*/
好的算法1(结构体)
c语言
// 这是用的结构体原理,这也是一般人看见这个题目一般的好的想法
// 个人推荐,但是后面还有个更好的写法
#include<stdio.h>
struct birth
{
char name[6];
int y;
int m;
int d;
}a, max, min;
int main()
{
int n, cnt = 0;
scanf("%d", &n); // 几个待处理的数据
max.y = 2014; max.m = 9;max.d = 7; // 两个边界
min.y = 1814; max.m = 9; max.d = 5;
cnt = n;
for(int i = 0; i < n; i++)
{
scanf("%s %d/%d/%d", &a.name, &a.y, &a.m, &a.d); // 按题目要求的输入
if(a.y > 2014 || (a.y == 2014 && a.m > 9) || (a.y == 2014 && a.m == 9 && a.d > 6) || a.y < 1814 || (a.y == 1814 && a.m < 9) || (a.y == 1814 && a.m == 9 && a.d < 6))
{
cnt--; // 这个if条件里面包含的了所有非法的条件,每次不满足条件就cnt(总处理个数-1)
continue; // 让后跳过这次循环
}
if(a.y < max.y || (a.y == max.y && a.m < max.m) || (a.y == max.y && a.m == max.m && a.d < max.d))
{
max = a; // 这个是找最大的情况的一个判断
}
if(a.y > min.y || (a.y == min.y && a.m > min.m) || (a.y == min.y && a.m == min.m && a.d > min.d))
{
min = a; // 这个是找最小的情况的一个判断
}
}
printf("%d", cnt); // 输出
if(cnt != 0)
{
printf(" %s %s",max.name, min.name);
}
return 0;
}
好的算法2(不使用结构体)
// 这是一个不用结构体的方法
#include <iostream>
using namespace std;
#include <cstring>
int main()
{
char max[6], min[6], name[6]; // 用来装名字的
int year, mon, day; // 用来装年月日的
int n, cnt = 0, flag = 0;
long long bm = 20140906, bi = 18140906, temp, m1 = 0, m2 = 0; // 看到这里就知道这个原理了,就是把出生日期转化为数字来对比,一定要用long long 不然可能数据溢出
scanf ("%d", &n); // 待处理的数据个数
for (int i = 0; i < n; i++)
{
scanf ("%s %d/%d/%d", name, &year, &mon, &day); // 输入年月日
temp = year * 10000 + mon * 100 + day; // 进行格式转换
if (temp >= bi && temp <= bm) // 简单的判断看看是否在要求的界限范围内
{
cnt++;
if (flag == 0) // 标记用的,最大,最小都用第一个初始化
{
m1= temp;
strcpy(max, name);
m2 = temp;
strcpy(min, name);
flag = 1;
}
else
{
if (temp > m1) // 这里就是很常见的找最大,最小的判断了
{
m1 = temp;
strcpy(max, name);
}
if (temp < m2)
{
m2 = temp;
strcpy(min, name);
}
}
}
}
cout << cnt << " " << min << " " << max << endl;
return 0;
}