CSP CCF:201712-3 Crontab(C++)

题目来源

Crontab

参考文章

201712-3 Crontab ccf

提示与数据特征

在这里插入图片描述

知识点

  1. string 转 char:

     参考文章: [C++ string 转 char*](https://www.cnblogs.com/mrguoguo/p/14435621.html#:~:text=c%2B%2B%20string%E8%BD%ACchar%2A%201%E3%80%81%E5%A6%82%E6%9E%9C%E8%A6%81%E5%B0%86string%E8%BD%AC%E6%8D%A2%E4%B8%BAchar%2A%EF%BC%8C%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8string%E6%8F%90%E4%BE%9B%E7%9A%84%E5%87%BD%E6%95%B0c_str%20%28%29%20%EF%BC%8C%E6%88%96%E6%98%AF%E5%87%BD%E6%95%B0data,%28%29%EF%BC%8Cdata%E9%99%A4%E4%BA%86%E8%BF%94%E5%9B%9E%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%86%85%E5%AE%B9%E5%A4%96%EF%BC%8C%E4%B8%8D%E9%99%84%E5%8A%A0%E7%BB%93%E6%9D%9F%E7%AC%A6%270%27%EF%BC%8C%E8%80%8Cc_str%20%28%29%E8%BF%94%E5%9B%9E%E4%B8%80%E4%B8%AA%E4%BB%A5%E2%80%980%E2%80%99%E7%BB%93%E5%B0%BE%E7%9A%84%E5%AD%97%E7%AC%A6%E6%95%B0%E7%BB%84%E3%80%82%202%E3%80%81const%20char%20%2Ac_str%20%28%29%3B)
     string 转 char[]
     char c[20];
     string s="1234";
     strcpy(c,s.c_str());
     这样才不会出错,c_str()返回的是一个临时指针,不能对其进行操作
     注意:一定要使用strcpy()函数 等来操作方法c_str()返回的指针.
    
     string 转 char*
     string s = "1234"
     const char* cs = s.c_str();  //必须得const, 不然会报错
    
     char* 转 string
     char* cs = "1234";
     string str = cs;
    
     char[] 转 string
     char cs[5] = "1234";
     string str = cs;
    
  2. string 小写 借助 tolower(char)函数

  3. string 转 数字或其他

     	1. sscanf(orignal,"%xxx", dest); 
     	string a = "123";
     	int b;
     	如 sscanf(a, "%d", b);
     	就将a(“123”)转为b(123)了
     	2. stringstream
     	string itos_x(int a) {
     	    stringstream ss;
     	    ss << a;
     	    return ss.str();
     	}
     	
     	int stoi_x(string a) {
     	    int b;
     	    stringstream ss(a);
     	    ss >> b;
     	    return b;
     	}
    
  4. size_t , string.find(char) , string::npos

     string b = "1,3-4";
     int index = b.find(',');   // 1
     while (index != b.npos) {   // i存在 "," 时
     ...
     }
    

注意事项

  1. 需要判断当前月份的天数是否超过月份天数
  2. 对每个时间节点的执行命令需要去重
  3. 在添加满足条件的时间节点和命令时记得判断时间节点是否满足[s,t) (可以直接用str来比较)
  4. 闰年是 年数为4的倍数但不能被100整除,或者年数能被400整除的年。
  5. 对于一些 if else 可以考虑 xx = xxxx? x: xxx;

解题思路

看代码吧

代码

#include <bits/stdc++.h>

using namespace std;
#define MAXN 1000

int N;
string starttime, endtime;
int syyyy, smm, sdd, sHH, sMM;
int eyyyy, emm, edd, eHH, eMM;
map<int, int> mont2day = {{1, 31}, {2, 28}, {3, 31}, {4, 30}, {5, 31}, {6, 30}, {7, 31}, {8, 31}, {9, 30}, {10, 31}, {11, 30}, {12, 31}};
map<string, int> mont2int = {{"jan", 1}, {"feb", 2}, {"mar", 3}, {"apr", 4}, {"may", 5}, {"jun", 6}, {"jul", 7}, {"aug", 8}, {"sep", 9}, {"oct", 10}, {"nov", 11}, {"dec", 12}};
map<string, int> week2int = {{"sun", 0}, {"mon", 1}, {"tue", 2}, {"wed", 3}, {"thu", 4}, {"fri", 5}, {"sat", 6}};
map<string, vector<string> > ans;

bool isleapyear(int year) {
    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}

void lowerStr(string &str) {
    for (int i = 0; i < str.size(); ++i) {
        str[i] = tolower(str[i]);
    }
}

string itos_x(int a) {
    stringstream ss;
    ss << a;
    return ss.str();
}

int stoi_x(string a) {
    int b;
    stringstream ss(a);
    ss >> b;
    return b;
}

void getSE() {
    syyyy = stoi_x(starttime.substr(0, 4)); smm = stoi_x(starttime.substr(4, 2)); sdd = stoi_x(starttime.substr(6,2)); sHH = stoi_x(starttime.substr(8, 2)); sMM = stoi_x(starttime.substr(10, 2));
    eyyyy = stoi_x(endtime.substr(0, 4)); emm = stoi_x(endtime.substr(4, 2)); edd = stoi_x(endtime.substr(6, 2)); eHH = stoi_x(endtime.substr(8, 2)); eMM = stoi_x(endtime.substr(10, 2));
}

vector<int> f1(string b, int type) {  // [type] 0: others; 1: month; 2:weekday
    if (b[b.size() - 1] != ',') {
        b += ',';
    }

    vector<int> a;

    int index = b.find(',');
    while (index != b.npos) {  // 遍历字符串
        string cur = b.substr(0, index);
        b = b.substr(index + 1, (b.size() - index - 1));

        int mindex = cur.find('-');
        if (mindex != cur.npos) {  // 是范围
            string left = cur.substr(0, mindex), right = cur.substr(mindex + 1, cur.size() - mindex - 1);
            int intleft, intright;
            if (type == 1) {
                if (isalpha(left[0])) intleft = mont2int[left];
                else intleft = stoi_x(left);
                if (isalpha(right[0])) intright = mont2int[right];
                else intright = stoi_x(right);
            }
            else if (type == 2) {
                if (isalpha(left[0])) intleft = week2int[left];
                else intleft = stoi_x(left);
                if (isalpha(right[0])) intright = week2int[right];
                else intright = stoi_x(right);
            }
            else {
                intleft = stoi_x(left);
                intright = stoi_x(right);
            }

            while (intleft <= intright) {
                a.push_back(intleft);
                ++intleft;
            }
        }
        else {  // 不是范围
            int num ;
            if (type == 1 && isalpha(cur[0])) num = mont2int[cur];
            else if (type == 2 && isalpha(cur[0])) num = week2int[cur];
            else num = stoi_x(cur);
            a.push_back(num);
        }
        index = b.find(',');
    }

    return a;
}

int getWeekday(int year, int month, int day) {
    long long days = 0;
    int y = 1970, m = 1;
    while (y < year) {
        if (isleapyear(y)) days += 366;
        else days += 365;
        ++y;
    }
    while (m < month) {
        /*if (isleapyear(year) && m == 2) days += 29;
        else if (m == 2) days += 28;
        else days += mont2day[m];*/
        days += mont2day[m];
        ++m;
    }
    days += day - 1;

    return (4 + days % 7) % 7;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie();
    cout.tie();

    ifstream cin("in2.txt");

    cin>>N>>starttime>>endtime;
    getSE();

    //输入
    for (int i = 0; i < N; ++i) {
        string mi, ho, dm, mo, dw, co;
        cin>>mi>>ho>>dm>>mo>>dw>>co;

        // 小写
        lowerStr(mo);
        lowerStr(dw);

        // 存储
        vector<int> minutes, hours, dom, month, dow;
        string command;
        if (mi == "*") mi = "0-59";
        minutes = f1(mi, 0);
        if (ho == "*") ho = "0-23";
        hours = f1(ho, 0);
        if (dm == "*") dm = "1-31";
        dom = f1(dm, 0);
        if (mo == "*") mo = "1-12";
        month = f1(mo, 1);
        if (dw == "*") dw = "0-6";
        dow = f1(dw, 2);
        command = co;

        /*
        // 输出
        cout<<"lalalala:"<<endl;
        for (int mm: dow) cout<<mm<<" ";
        cout<<endl;
        */

        // 存week, 方便筛选
        set<int> candweek;
        for (int w: dow) candweek.insert(w);

        // 存答案哈
        for (int yearr = syyyy; yearr <= eyyyy; ++yearr) {
            if (isleapyear(yearr)) mont2day[2] = 29;
            else mont2day[2] = 28;
            string stryear = itos_x(yearr);

            for (int monthh: month) {
                string strmonth = itos_x(monthh);
                if (strmonth.size() == 1) strmonth = "0" + strmonth;

                for (int dayy: dom) {
                    string strday = itos_x(dayy);
                    if (strday.size() == 1) strday = "0" + strday;
                    int curweek = getWeekday(yearr, monthh, dayy);
                    if (candweek.count(curweek) == 0 || dayy > mont2day[monthh]) continue;  // ~ 由 30 跳到 95  dayy > mont2day[monthh] 需要判断当前月份的天数是否超过月份天数

                    for (int hourr: hours) {
                        string strhour = itos_x(hourr);
                        if (strhour.size() == 1) strhour = "0" + strhour;

                        for (int minutee: minutes) {
                            string strminute = itos_x(minutee);
                            if (strminute.size() == 1) strminute = "0" + strminute;
                            string curtime = stryear + strmonth + strday + strhour + strminute;

                            if (curtime >= starttime && curtime < endtime) {  // ~ 可以直接用str来比较 ~
                                ans[curtime].push_back(command);  // 这样相当于自动根据curtime进行排序啦, 并且command是按照输入的顺序来的
                            }
                        }
                    }
                }
            }
        }
    }

    for (pair<string, vector<string> > p: ans) {
        map<string, int> ifrepeated;  // 去重, 从95 跳到 100
        for (string s: p.second) {
            if (ifrepeated.count(s) != 0) continue;
            cout<<p.first<<" "<<s<<endl;
            ifrepeated[s] = 1;
        }
    }

    //cout<<ans.size()<<endl;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值