这道题目可以从以下几点来分析,遍历给定起点到终点的每一分钟,然后去配置文件中查找,但是这样会超时,我们转化一下思路,遍历配置文件中的时间,根据产生的日期检查其是否有效,这样检查的时间大大减少。
工具函数准备
利用stringstream实现string和int之间的相互转化。
string int_to_string(int a){
/**
* 将给定的整数变为字符串
*/
ostringstream ostringstream1;
ostringstream1<<a; // 将a写入流中
return ostringstream1.str(); // 从流中获取到对应的整数
}
int string_to_int(const string & str){
/**
* 将给定的字符串变为整数
*/
int num;
istringstream ss(str);
ss >> num;
return num;
}
计算给定时间是星期几
题目中给出我们1970-01-01是星期四,我们只要算出给定时间到这个基准时间的天数,然后就可以算出是星期几了。
int getweek(const string & date){
/**
* date的格式是 yyyymmddHHMM是一个长度为12的字符串
* 根据1970-01-01是星期四开始推算
*/
int yyyy = string_to_int(date.substr(0, 4));
int mm = string_to_int(date.substr(4, 2));
int dd = string_to_int(date.substr(6, 2));
int HH = string_to_int(date.substr(8, 2));
int MM = string_to_int(date.substr(10, 2));
// 先算年
int sum = 0;
for (int i = 1970; i < yyyy; ++i) {
sum += isLeap(i)?366:365;
}
// 再算月
if (isLeap(yyyy)) Daysofmon[2] = 29;
else Daysofmon[2] = 28;
for (int i = 1; i < mm; ++i) {
sum += Daysofmon[i];
}
// 再算日子
sum += dd-1;
return (4+sum)%7;
}
将每一条配置信息放到对应的vector中
string getweek(const string & cyyyy, const string & cmm, const string & cdd) {
/**
* date的格式是 yyyymmddHHMM是一个长度为12的字符串
* 根据1970-01-01是星期四开始推算
*/
int yyyy = string_to_int(cyyyy);
int mm = string_to_int(cmm);
int dd = string_to_int(cdd);
// 先算年
int sum = 0;
for (int i = 1970; i < yyyy; ++i) {
sum += isLeap(i) ? 366 : 365;
}
// 再算月
if (isLeap(yyyy)) Daysofmon[2] = 29;
else Daysofmon[2] = 28;
for (int i = 1; i < mm; ++i) {
sum += Daysofmon[i];
}
// 再算日子
sum += dd - 1;
return int_to_string((4 + sum) % 7);
}
最后贴上全部代码
#include <bits/stdc++.h>
using namespace std;
char Month[][4]={"","jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"};
char Week[][4]={"sun","mon","tue","wed","thu","fri","sat"};
int Daysofmon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
map<string, int> weekmap, monthmap;
int n;
map<string, vector<string> > map1;
string int_to_string(int a) {
/**
* 将给定的整数变为字符串
*/
ostringstream ostringstream1;
ostringstream1 << a; // 将a写入流中
return ostringstream1.str(); // 从流中获取到对应的整数
}
int string_to_int(const string &str) {
/**
* 将给定的字符串变为整数
*/
int num;
istringstream ss(str);
ss >> num;
return num;
}
bool isLeap(int year) {
return (year % 400 == 0) || (year % 100 != 0 && year % 4 == 0);
}
string getweek(const string & cyyyy, const string & cmm, const string & cdd) {
/**
* date的格式是 yyyymmddHHMM是一个长度为12的字符串
* 根据1970-01-01是星期四开始推算
*/
int yyyy = string_to_int(cyyyy);
int mm = string_to_int(cmm);
int dd = string_to_int(cdd);
// 先算年
int sum = 0;
for (int i = 1970; i < yyyy; ++i) {
sum += isLeap(i) ? 366 : 365;
}
// 再算月
if (isLeap(yyyy)) Daysofmon[2] = 29;
else Daysofmon[2] = 28;
for (int i = 1; i < mm; ++i) {
sum += Daysofmon[i];
}
// 再算日子
sum += dd - 1;
return int_to_string((4 + sum) % 7);
}
void initmap() {
for (int i = 0; i <= 6; ++i) {
weekmap[Week[i]] = i;
}
for (int i = 1; i <= 12; ++i) {
monthmap[Month[i]] = i;
}
}
void tostandard(string & str){
for (int i = 0; i < str.size(); ++i) {
if (isalpha(str[i]))
str[i] = tolower(str[i]);
}
}
vector<string> buildvector(string &str, int type = 0) {
/**
* type一共三种,当key为1是,表示建立week,当key为2时,表示建立month
* 其他的为0
*/
vector<string> retvec;
str += ",";
int ix;
while ((ix = str.find(',')) != string::npos) {
//查找-
string temp = str.substr(0, ix);
str = str.substr(ix + 1);
int fx;
if ((fx = temp.find('-')) != string::npos) {//说明是连续的数
string ls = temp.substr(0, fx);
string rs = temp.substr(fx + 1);
int lix, rix;
if (isalpha(ls[0])) {
if (type == 1) lix = weekmap[ls];
else lix = monthmap[ls];
} else lix = string_to_int(ls);
if (isalpha(rs[0])) {
if (type == 1) rix = weekmap[rs];
else rix = monthmap[rs];
} else rix = string_to_int(rs);
// 这样都转化为整数
for (int i = lix; i <= rix; ++i) {
retvec.push_back(int_to_string(i));
}
} else {//说明是一个数
if (isalpha(temp[0])) {
// 说明需要转换
if (type == 1) retvec.push_back(int_to_string(weekmap[temp]));
else retvec.push_back(int_to_string(monthmap[temp]));
} else
retvec.push_back(temp);
}
}
return retvec;
}
int main() {
// freopen("../in.txt", "r", stdin);
cin>>n;
string stime, etime;
cin>>stime>>etime;
int syyyy = string_to_int(stime.substr(0, 4));
int eyyyy = string_to_int(etime.substr(0, 4));
initmap();
while (n--){// 对每一条配置项进行解析
string minutes, hours, day_of_month, month, day_of_week, command;
cin>>minutes>>hours>>day_of_month>>month>>day_of_week>>command;
tostandard(month);
tostandard(day_of_week);
if (minutes=="*") minutes="0-59";
vector<string> vminutes = buildvector(minutes, 0);
if (hours == "*") hours = "0-23";
vector<string> vhours = buildvector(hours, 0);
if (day_of_month == "*") day_of_month="1-31";
vector<string> vday_of_month = buildvector(day_of_month, 0);
if (month == "*") month = "1-12";
vector<string> vmonth = buildvector(month, 2);
if (day_of_week == "*") day_of_week="0-6";
vector<string> vday_of_week = buildvector(day_of_week, 1);
set<string> set1(vday_of_week.begin(), vday_of_week.end());
// 对前面的四项进行遍历,然后根据星期几和时间的合法性进行取舍
//从当前年开始遍历
int tempyyyy = syyyy;
while (tempyyyy<=eyyyy){
if (isLeap(tempyyyy)) Daysofmon[2] = 29;
else Daysofmon[2] = 28;
for (int i = 0; i < vmonth.size(); ++i) {
for (int j = 0; j < vday_of_month.size(); ++j) {
string cyyyy = int_to_string(tempyyyy);
string cmm = vmonth[i];
string cdd = vday_of_month[j];
// 这个判断是最重要的一部分的
if (Daysofmon[string_to_int(cmm)]<string_to_int(cdd)||set1.count(getweek(cyyyy, cmm, cdd))==0) continue;
for (int k = 0; k < vhours.size(); ++k) {
for (int m = 0; m < vminutes.size(); ++m) {
string ss = cyyyy+(cmm.size()>1?cmm:"0"+cmm)+(cdd.size()>1?cdd:"0"+cdd)
+(vhours[k].size()>1?vhours[k]:"0"+vhours[k])+(vminutes[m].size()>1?vminutes[m]:"0"+vminutes[m]);
if (ss>=stime&&ss<etime){
map1[ss].push_back(command);
}
}
}
}
}
tempyyyy++;
}
}
// 全部结束之后开始打印结果
map<string , vector<string> >::iterator it = map1.begin();
for (; it!=map1.end(); it++){
set<string> set1;
for (int i = 0; i < it->second.size(); ++i) {
if (set1.count(it->second[i])==0){
cout<<it->first<<" "<<it->second[i]<<endl;
set1.insert(it->second[i]);
}
}
}
}
主要参考了这篇博客:
传送门