CCF CSP Crontab

这道题目可以从以下几点来分析,遍历给定起点到终点的每一分钟,然后去配置文件中查找,但是这样会超时,我们转化一下思路,遍历配置文件中的时间,根据产生的日期检查其是否有效,这样检查的时间大大减少。

工具函数准备

利用stringstream实现string和int之间的相互转化。

string int_to_string(int a){
    /**
     * 将给定的整数变为字符串
     */
    ostringstream ostringstream1;
    ostringstream1<// 将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 

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)]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// 全部结束之后开始打印结果
    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<first<<" "<second[i]<second[i]);
            }
        }
    }
}

主要参考了这篇博客:
传送门

你可能感兴趣的:(ccf,csp)