累了就写个大模拟+博客,不得不说,意外的还挺减压
这题相比猪国杀简单不少,但是细节也挺多,还是考验实现能力。
说几个我觉得比较重要的实现的地方:
1 对于所有的时间,无论是分+秒,时+分+秒,日期,其实都可以转化成秒,因为2017年的秒数远小于int
范围(大约也就7次方的水平),这样能够在特判的时候减少非常多的码量。同时最好每一条判断单独一个函数,可以直接return
,一个else
都不需要,也是降低了码量。
2 千米转化成米就没有浮点数问题了,同时除法尽可能写乘法,避开调精度。
除此之外就是一些坑:
1 注意所谓的时间相隔6小时是和上一次合法记录的,不合法的不算,同理,也不见得第一次取完之后就可以开始判断相隔这个条件了。
2 虽然并不存在,但是其实应该留意一下跑步跨过了一天的情况。
3 x个月的天数并不是28/30/31的倍数,更不是100天的倍数,记得预处理。
4 先计算阳光长跑计划,再加上专项计划算出勤。
5 跑步的时候是不低于该档算该档的分数(真的差一点就写错了)。
代码如下:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<unordered_map>
#include<cassert>
using namespace std;
const int N = 1e4 + 1;
const double eps = 1e-8;
struct run{
long long date;
double l;
int st,ed,stp,step;
};
vector<run> v[N];
unordered_map<long long,int> mp;
int cnt[N],sum[N],mon[13] = {0,31,59,90,120,151,181,212,243,273,304,334,365};
long long id[N];
char tim[11],s[11],sex[N][2],heal[2],t[11];
bool flag[N];
int calctime1(){
int x,y,z;
x = (tim[1] - '0') * 10 + tim[2] - '0';
y = (tim[4] - '0') * 10 + tim[5] - '0';
z = (tim[7] - '0') * 10 + tim[8] - '0';
return x * 3600 + y * 60 + z;
}//计算xx:yy:zz
int calctime2(){
int i = 1,x = 0,y = 0,m;
m = strlen(tim + 1);
while(tim[i] >= '0' && tim[i] <= '9'){
x = x * 10 + tim[i] - '0';
++i;
}
++i;
while(i <= m && tim[i] >= '0' && tim[i] <= '9'){
y = y * 10 + tim[i] - '0';
++i;
}
return x * 60 + y;
}//计算a'b''
int calctime3(){
int x,y;
x = (tim[5] - '0') * 10 + tim[6] - '0';
y = (tim[7] - '0') * 10 + tim[8] - '0';
return mon[x - 1] + y;
} //计算2017xxyy
int exam(int id){
int x = calctime2();
if(flag[id]){
if(x <= 750) return 20;
if(x <= 780) return 18;
if(x <= 810) return 16;
if(x <= 840) return 14;
if(x <= 870) return 12;
if(x <= 910) return 10;
if(x <= 950) return 8;
if(x <= 990) return 6;
if(x <= 1030) return 4;
if(x <= 1080) return 2;
return 0;
}
else{
if(x <= 400) return 20;
if(x <= 417) return 18;
if(x <= 434) return 16;
if(x <= 451) return 14;
if(x <= 470) return 12;
if(x <= 485) return 10;
if(x <= 500) return 8;
if(x <= 515) return 6;
if(x <= 530) return 4;
if(x <= 540) return 2;
return 0;
}
}//测试成绩
int runsc(int x){
if(x >= 21) return 10;
if(x >= 19) return 9;
if(x >= 17) return 8;
if(x >= 14) return 7;
if(x >= 11) return 6;
if(x >= 7) return 4;
if(x >= 3) return 2;
return 0;
}//阳光长跑
int attend(int x){
if(x >= 18) return 5;
if(x >= 15) return 4;
if(x >= 12) return 3;
if(x >= 9) return 2;
if(x >= 6) return 1;
return 0;
}//出勤
int longrun(int id){
#define u v[id][i]//减少码量
int i,ret,ccnt = 0;
long long lst,lstdate,ti,delta;
bool valid,ok = 0;
for(i = 0;i < (int)v[id].size();i++){
valid = 1;
assert(u.ed > u.st);
if(u.ed < u.st){
ti = u.ed + 86400 - u.st;
--u.date;
}
else ti = (u.ed - u.st);
if(u.stp > 270) valid = 0;
if((int)u.l < 2 * ti || (int)u.l > 5 * ti) valid = 0;
if(flag[id] && u.l < 3000 || !flag[id] && u.l < 1500) valid = 0;
if(u.l > 1.5 * u.step) valid = 0;
if(ok){
delta = (u.date - lstdate) * 86400 + u.st - lst;
if(delta < 21600) valid = 0;
}
if(valid){
ok = 1;
lstdate = u.date,lst = u.ed;
++ccnt;
//只有出现合法解之后再考虑相隔不超6小时的条件
}
}
ret = runsc(ccnt);
cnt[id] += ccnt;
ret += attend(cnt[id]);
return ret;
}
string grade(int sc){
if(sc >= 95) return "A";
if(sc >= 90) return "A-";
if(sc >= 85) return "B+";
if(sc >= 80) return "B";
if(sc >= 77) return "B-";
if(sc >= 73) return "C+";
if(sc >= 70) return "C";
if(sc >= 67) return "C-";
if(sc >= 63) return "D+";
if(sc >= 60) return "D";
return "F";
}//利用string便于继续用前面的方法返回分数
int main(){
int i,n,tt,temp;
long long lemp;
scanf("%d",&tt);
for(i = 1;i <= tt;i++){
scanf("%lld",&id[i]);
mp[id[i]] = i;
scanf("%s",sex[i] + 1);
if(sex[i][1] == 'M') flag[i] = 1;
scanf("%d",&sum[i]);
scanf("%s",tim + 1);
sum[i] += exam(i);
scanf("%s",heal + 1);
if(heal[1] == 'P') sum[i] += 10;
scanf("%d",&temp);
sum[i] += temp;
scanf("%d",&cnt[i]);
}
scanf("%d",&n);
run s;
for(i = 1;i <= n;i++){
scanf("%s",tim + 1);
s.date = calctime3();
scanf("%lld",&lemp);
temp = mp[lemp];
scanf("%s",tim + 1);
s.st = calctime1();
scanf("%s",tim + 1);
s.ed = calctime1();
scanf("%lf",&s.l);
s.l *= 1000;
scanf("%s",tim + 1);
s.stp = calctime2();
scanf("%d",&s.step);
v[temp].push_back(s);
}
for(i = 1;i <= tt;i++){
sum[i] += longrun(i);
printf("%lld ",id[i]);
printf("%d ",sum[i]);
cout << grade(sum[i]) << endl;
}
return 0;
}
Thank you for reading 😃