├── .gitignore ├── 201312-2ISBN号码.cpp ├── 201312-3最大矩形.cpp ├── 201403-2窗口.cpp ├── 201403-3命令行选项.cpp ├── 201604-1折点计数.cpp ├── 201604-2俄罗斯方块.cpp ├── 201604-3路径解析.cpp ├── 201609-1最大波动.cpp ├── 201609-2火车购票.cpp ├── 201612-1中间数.cpp ├── 201612-2工资计算.cpp ├── 201612-3权限查询.cpp ├── 201703-1分蛋糕.cpp ├── 201703-2学生排队.cpp ├── 201703-3Markdown.cpp ├── 201709-1打酱油.cpp ├── 201709-2公共钥匙盒.cpp ├── 201709-3JSON查询.cpp ├── 201712-1最小差值.cpp ├── 201712-2游戏.cpp ├── 201712-3Crontab.cpp ├── 201803-1跳一跳.cpp ├── 201803-2碰撞的小球.cpp ├── 201803-3URL映射.cpp └── README.md /.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeigo/CCF-CSP/ac18abd44bb9ee5571c8099db59657e5735c6be0/.gitignore -------------------------------------------------------------------------------- /201312-2ISBN号码.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main(int argc, char const *argv[]) 6 | { 7 | string isbn; 8 | cin >> isbn; 9 | int code = 0, factor = 1; 10 | for(int i = 0; i < 11; i++) { 11 | if(i == 1 || i == 5) continue; 12 | code += factor * (isbn[i] - '0'); 13 | factor++; 14 | } 15 | code %= 11; 16 | char last = code == 10 ? 'X' : '0' + code; 17 | if(last == isbn[12]) { 18 | cout << "Right"; 19 | } else { 20 | isbn[12] = last; 21 | cout << isbn; 22 | } 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /201312-3最大矩形.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main(int argc, char const *argv[]) 6 | { 7 | int n; 8 | cin >> n; 9 | vector heights(n); 10 | for(int i = 0; i < n; i++) { 11 | int x; 12 | cin >> x; 13 | heights[i] = x; 14 | } 15 | // left[i]:i左边连续不小于heights[i]的个数 16 | vector left(n), right(n); 17 | left.front() = 0; 18 | for(int i = 1; i < n; i++) { 19 | if(heights[i] > heights[i - 1]) { 20 | left[i] = 0; 21 | } else { 22 | left[i] = 1 + left[i - 1]; 23 | int j = i - left[i] - 1; // 不能确定的位置 24 | while(j >= 0 && heights[j] >= heights[i]) { 25 | left[i]++; j--; 26 | } 27 | } 28 | } 29 | right.back() = 0; 30 | for(int i = n - 2; i >= 0; i--) { 31 | if(heights[i] > heights[i + 1]) { 32 | right[i] = 0; 33 | } else { 34 | right[i] = 1 + right[i + 1]; 35 | int j = i + right[i] + 1; // 不能确定的位置 36 | while(j < n && heights[j] >= heights[i]) { 37 | right[i]++; j++; 38 | } 39 | } 40 | } 41 | int max_area = 0; 42 | for(int i = 0; i < n; i++) { 43 | max_area = max(max_area, heights[i] * (left[i] + right[i] + 1)); 44 | } 45 | cout << max_area; 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /201403-2窗口.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | struct Win { 6 | int num; 7 | int left; 8 | int top; 9 | int right; 10 | int bottom; 11 | Win(int n, int l, int t, int r, int b) : num(n), left(l), top(t), right(r), bottom(b) {} 12 | }; 13 | // 判断坐标是否在窗口内 14 | bool in_win(int x, int y, Win &w); 15 | 16 | int main(int argc, char const *argv[]) 17 | { 18 | int n, m; 19 | cin >> n >> m; 20 | list wins; 21 | for(int i = 0; i < n; i++) { 22 | int left, top, right, bottom; 23 | cin >> left >> top >> right >> bottom; 24 | wins.push_back(Win(i + 1, left, top, right, bottom)); 25 | } 26 | while(m--) { 27 | int x, y; 28 | cin >> x >> y; 29 | bool is_found = false; 30 | for(list::iterator it = --wins.end(); it != --wins.begin(); it--) { 31 | if(in_win(x, y, *it)) { 32 | cout << it->num << endl; 33 | wins.push_back(*it); 34 | wins.erase(it); 35 | is_found = true; 36 | break; 37 | } 38 | } 39 | if(!is_found) { 40 | cout << "IGNORED" << endl; 41 | } 42 | } 43 | return 0; 44 | } 45 | 46 | bool in_win(int x, int y, Win &w) { 47 | return w.left <= x && w.right >= x && w.top <= y && w.bottom >= y; 48 | } -------------------------------------------------------------------------------- /201403-3命令行选项.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | // 按' '分割str 9 | vector split_str(string &str); 10 | 11 | int main(int argc, char const *argv[]) 12 | { 13 | string optstr; 14 | cin >> optstr; 15 | set opts, opts_arg; // opts无参选项集合,opts_arg有参选项集合 16 | for(int i = 0; i < optstr.size(); i++) { 17 | if((i + 1 < optstr.size()) && optstr[i + 1] == ':') { 18 | opts_arg.insert("-" + optstr.substr(i, 1)); 19 | i++; 20 | } else { 21 | opts.insert("-" + optstr.substr(i, 1)); 22 | } 23 | } 24 | int n; 25 | cin >> n; 26 | getchar(); 27 | for(int i = 0; i < n; i++) { 28 | string cmd; 29 | getline(cin, cmd); 30 | vector args = split_str(cmd); 31 | map buffer; 32 | for(int j = 1; j < args.size(); j++) { 33 | string arg = args[j]; 34 | if(opts.find(arg) != opts.end()) { // arg为无参选项 35 | buffer[arg] = string(""); 36 | } else if(opts_arg.find(arg) != opts_arg.end()) { // arg为有参选项 37 | if(j + 1 < args.size()) { // 确保j不是最后一个 38 | buffer[arg] = args[j + 1]; 39 | j++; 40 | } 41 | } else { 42 | break; 43 | } 44 | } 45 | cout << "Case " << i + 1 << ": "; 46 | for(map::iterator it = buffer.begin(); it != buffer.end(); it++) { 47 | if(it->second.empty()) { 48 | cout << it->first << " "; 49 | } else { 50 | cout << it->first << " " << it->second << " "; 51 | } 52 | } 53 | cout << endl; 54 | } 55 | return 0; 56 | } 57 | 58 | vector split_str(string &str) { 59 | str += " "; 60 | stringstream ss(str); 61 | vector res; 62 | string tmp; 63 | while(getline(ss, tmp, ' ')) { 64 | res.push_back(tmp); 65 | } 66 | return res; 67 | } 68 | -------------------------------------------------------------------------------- /201604-1折点计数.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main() { 6 | int n; 7 | cin >> n; 8 | vector vi; 9 | while(n--) { 10 | int x; 11 | cin >> x; 12 | vi.push_back(x); 13 | } 14 | int cnt = 0; 15 | for(int i = 1; i < vi.size() - 1; i++) { 16 | if((vi[i] > vi[i - 1] && vi[i] > vi[i + 1]) || (vi[i] < vi[i - 1] && vi[i] < vi[i + 1])) { 17 | cnt++; 18 | } 19 | } 20 | cout << cnt; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /201604-2俄罗斯方块.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | void cin_matrix(vector > &vv, int row, int col); 6 | 7 | int main() { 8 | // 输入graph 9 | vector > graph(15, vector(10)); 10 | cin_matrix(graph, 15, 10); 11 | // 输入block 12 | vector > block(4, vector(4)); 13 | cin_matrix(block, 4, 4); 14 | int start; 15 | cin >> start; 16 | start--; 17 | // 找到block每列最下方块的位置,没有时为-20 18 | vector bottom(4, -20); 19 | for(int i = 0; i < 4; i++) { 20 | for(int j = 3; j >= 0; j--) { 21 | if(block[j][i]) { 22 | bottom[i] = j; break; 23 | } 24 | } 25 | } 26 | // 计算对应列block最下方块与graph最上方块间距,找到最小,即为整个block需要下移的距离 27 | int min_dis = 19; 28 | for(int i = 0; i < 4; i++) { 29 | int k; 30 | for(k = 0; k < 15; k++) { // 从graph顶端往下 31 | if(graph[k][i + start]) { 32 | break; 33 | } 34 | } 35 | if(3 - bottom[i] + k < min_dis) { 36 | min_dis = 3 - bottom[i] + k; 37 | } 38 | } 39 | // 假设block[j][i]在graph[j-4][start + i]位置 40 | for(int i = 0; i < 4; i++) { 41 | for(int j = 0; j <= bottom[i]; j++) { 42 | graph[j - 4 + min_dis][start + i] = block[j][i]; // 从j-4下移min_dis 43 | } 44 | } 45 | for(int i = 0; i < 15; i++) { 46 | for(int j = 0; j < 10; j++) { 47 | cout << graph[i][j] << " "; 48 | } 49 | cout << endl; 50 | } 51 | return 0; 52 | } 53 | 54 | void cin_matrix(vector > &vv, int row, int col) { 55 | int x; 56 | for(int i = 0; i < row; i++) { 57 | for(int j = 0; j < col; j++) { 58 | cin >> x; 59 | vv[i][j] = x; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /201604-3路径解析.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | int main(int argc, char const *argv[]) 8 | { 9 | int n; 10 | cin >> n; 11 | string pwd; 12 | cin >> pwd; 13 | getchar(); 14 | while(n--) { 15 | string path; 16 | getline(cin, path); // 注意path可能为空字符串,不能直接cin>>path,前面要getchar 17 | if(path == "") { 18 | cout << pwd << endl; 19 | } else { 20 | if(path[0] != '/') { 21 | path = pwd + "/" + path; 22 | } 23 | path += "/"; // 末尾补上"/"便于处理 24 | vector stk; 25 | stringstream ss(path); 26 | string tmp; 27 | while(getline(ss, tmp, '/')) { 28 | if(tmp == ".") continue; 29 | else if(tmp == "..") { 30 | if(!stk.empty()) stk.pop_back(); 31 | } else if(!tmp.empty()) { 32 | stk.push_back(tmp); 33 | } 34 | } 35 | if(stk.empty()) { 36 | cout << "/" << endl; 37 | } else { 38 | for(int i = 0; i < stk.size(); i++) { 39 | cout << "/" + stk[i]; 40 | } 41 | cout << endl; 42 | } 43 | } 44 | } 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /201609-1最大波动.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main() { 6 | int n; 7 | cin >> n; 8 | int x, y, _max = 0; 9 | cin >> x; 10 | for(int i = 1; i < n; i++) { 11 | cin >> y; 12 | _max = max(_max, abs(y - x)); 13 | x = y; 14 | } 15 | cout << _max; 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /201609-2火车购票.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeigo/CCF-CSP/ac18abd44bb9ee5571c8099db59657e5735c6be0/201609-2火车购票.cpp -------------------------------------------------------------------------------- /201612-1中间数.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | typedef vector::iterator viit; 7 | 8 | int main() { 9 | int n; 10 | cin >> n; 11 | vector vi; 12 | for(int i = 0; i < n; i++) { 13 | int a; 14 | cin >> a; 15 | vi.push_back(a); 16 | } 17 | sort(vi.begin(), vi.end()); 18 | viit mid = vi.begin() + (n - 1) / 2; 19 | int value = *mid; 20 | viit low = lower_bound(vi.begin(), vi.end(), value), 21 | up = upper_bound(vi.begin(), vi.end(), value); 22 | if(n % 2 && up - mid == mid - low + 1) { // 1 2 2 2 3 23 | cout << value; 24 | } else if(n % 2 == 0 && up - mid == mid - low + 2) { // 1 2 2 3 25 | cout << value; 26 | } else { 27 | cout << -1; 28 | } 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /201612-2工资计算.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() { 6 | int t, s = 0; 7 | cin >> t; 8 | int money[8] = {3500, 1500, 3000, 4500, 26000, 20000, 25000, 300000}; 9 | float tax[8] = {0, 0.03, 0.1, 0.2, 0.25, 0.3, 0.35, 0.45}; 10 | int i = 0; 11 | while(i < 8 && t > 0) { 12 | if(t < money[i] * (1 - tax[i])) { 13 | s += t / (1 - tax[i]); 14 | break; 15 | } else { 16 | s += money[i]; 17 | t -= money[i] * (1 - tax[i]); 18 | i++; 19 | } 20 | } 21 | cout << s; 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /201612-3权限查询.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeigo/CCF-CSP/ac18abd44bb9ee5571c8099db59657e5735c6be0/201612-3权限查询.cpp -------------------------------------------------------------------------------- /201703-1分蛋糕.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() { 6 | int n, k; 7 | cin >> n >> k; 8 | int cake, count = 0, sum = 0; 9 | while(n--) { 10 | cin >> cake; 11 | sum += cake; 12 | if(sum >= k) { 13 | sum = 0; 14 | count++; 15 | } 16 | } 17 | if(sum > 0) count++; 18 | cout << count; 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /201703-2学生排队.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeigo/CCF-CSP/ac18abd44bb9ee5571c8099db59657e5735c6be0/201703-2学生排队.cpp -------------------------------------------------------------------------------- /201703-3Markdown.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeigo/CCF-CSP/ac18abd44bb9ee5571c8099db59657e5735c6be0/201703-3Markdown.cpp -------------------------------------------------------------------------------- /201709-1打酱油.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | 6 | int main(int argc, char const *argv[]) 7 | { 8 | int n, count; 9 | cin >> n; 10 | n /= 10; 11 | while(n >= 5) { 12 | n -= 5; 13 | count += 7; 14 | } 15 | while(n >= 3) { 16 | n -= 3; 17 | count += 4; 18 | } 19 | count += n; 20 | cout << count; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /201709-2公共钥匙盒.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int main(int argc, char const *argv[]) 9 | { 10 | int n, k; // n钥匙数,k使用数 11 | cin >> n >> k; 12 | vector keys(n); 13 | for(int i = 0; i < n; i++) { 14 | keys[i] = i + 1; 15 | } 16 | typedef map, vector > > Plan; 17 | Plan plan; // 某时要取/还的钥匙 18 | while(k--) { 19 | int w, s, c; // w编号,s取时,c时长 20 | cin >> w >> s >> c; 21 | plan[s].first.push_back(w); 22 | plan[s + c].second.push_back(w); 23 | } 24 | for(Plan::iterator it = plan.begin(); it != plan.end(); it++) { 25 | vector fetchs = it->second.first, backs = it->second.second; 26 | if(!backs.empty()) { // 先放回 27 | sort(backs.begin(), backs.end()); // 排序 28 | int j = 0; // 依次寻找空位,可利用上次找到的空位减少查询时间 29 | for(vector::iterator i = backs.begin(); i != backs.end(); i++) { 30 | while(j < n) { 31 | if(keys[j] == 0) { 32 | keys[j] = *i; 33 | j++; 34 | break; 35 | } 36 | j++; 37 | } 38 | } 39 | } 40 | if(!fetchs.empty()) { // 取钥匙,找到对应位置j即将keys[j]置为0 41 | for(vector::iterator i = fetchs.begin(); i != fetchs.end(); i++) { 42 | for(int j = 0; j < n; j++) { 43 | if(keys[j] == *i) { 44 | keys[j] = 0; 45 | break; 46 | } 47 | } 48 | } 49 | } 50 | } 51 | for(int i = 0; i < n; i++) { 52 | cout << keys[i] << " "; 53 | } 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /201709-3JSON查询.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | typedef map Kv; 8 | // 修剪空格 9 | void trim(string &str); 10 | // 转义 \\ \" 11 | void escape(string &str); 12 | // 根据去掉{}的json找出key-value,多层的记录"a.b" -> "", "a.b.c" -> "foo" 13 | void find_key_value(string &str, string prefix, Kv &kv); 14 | // 找到pos位置上'{'对应的'}'的位置 15 | int find_right_brace(string &str, int pos); 16 | 17 | int main(int argc, char const *argv[]) { 18 | int n, m; 19 | cin >> n >> m; 20 | getchar(); // 第一行换行 21 | string json; 22 | while(n--) { 23 | string line; 24 | getline(cin, line); 25 | json += line; 26 | } 27 | trim(json); 28 | json = json.substr(1, json.size() - 2); 29 | string prefix; 30 | Kv kv; 31 | find_key_value(json, prefix, kv); 32 | vector query(m); 33 | for(int i = 0; i < m; i++) { 34 | cin >> query[i]; 35 | } 36 | for(int i = 0; i < m; i++) { 37 | string key = query[i]; 38 | if(kv.find(key) != kv.end()) { 39 | if(kv[key].empty()) { 40 | cout << "OBJECT" << endl; 41 | } else { 42 | cout << "STRING " << kv[key] << endl; 43 | } 44 | } else { 45 | cout << "NOTEXIST" << endl; 46 | } 47 | } 48 | return 0; 49 | } 50 | 51 | void trim(string &str) { 52 | int pos = str.find(" "); 53 | while(pos != string::npos) { 54 | str.replace(pos, 1, ""); 55 | pos = str.find(" ", pos); 56 | } 57 | } 58 | 59 | void replace_all(string &str, char c) { 60 | int i = 0; 61 | while(i < str.size()) { 62 | if(str[i] == c && str[i - 1] == '\\') { 63 | str.erase(i - 1, 1); 64 | } else { 65 | i++; 66 | } 67 | } 68 | } 69 | 70 | void escape(string &str) { 71 | replace_all(str, '\"'); 72 | replace_all(str, '\\'); 73 | } 74 | 75 | void find_key_value(string &str, string prefix, Kv &kv) { 76 | str += ","; 77 | int start = 0, colon = str.find(":", start); 78 | while(colon != string::npos) { 79 | // 先找冒号:,从start到colon,去掉""后为key 80 | string key = str.substr(start + 1, colon - start - 2); 81 | escape(key); 82 | if(str[colon + 1] == '\"') { 83 | // colon后为'\"',value为string,寻找逗号comma,中间部分去掉""为value 84 | int comma = str.find(",", colon); 85 | string value = str.substr(colon + 2, comma - colon - 3); 86 | escape(value); 87 | kv[prefix + key] = value; 88 | start = comma + 1; 89 | } else if(str[colon + 1] == '{') { 90 | // colon后为'{',value为object,寻找匹配的右括号,中间部分去掉"",value递归 91 | int rightBrace = find_right_brace(str, colon + 1); 92 | string value = str.substr(colon + 2, rightBrace - colon - 2); 93 | kv[prefix + key] = string(); 94 | find_key_value(value, prefix + key + ".", kv); 95 | start = rightBrace + 2; 96 | } 97 | colon = str.find(":", start); 98 | } 99 | } 100 | 101 | int find_right_brace(string &str, int pos) { 102 | int stk = 1; 103 | for(int i = pos + 1; i < str.size(); i++) { 104 | if(str[i] == '{') stk++; 105 | else if(str[i] == '}') { 106 | stk--; 107 | if(stk == 0) return i; 108 | } 109 | } 110 | } 111 | 112 | -------------------------------------------------------------------------------- /201712-1最小差值.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | // 先排序,再比较相邻两元素的差值 6 | int main(int argc, char const *argv[]) 7 | { 8 | int n, x; 9 | vector vi; 10 | cin >> n; 11 | for(int i = 0; i < n; i++) { 12 | cin >> x; 13 | vi.push_back(x); 14 | } 15 | sort(vi.begin(), vi.end()); 16 | int minDiff = 10000; 17 | for(int i = 0; i < n - 1; i++) { 18 | minDiff = min(abs(vi[i] - vi[i + 1]), minDiff); 19 | } 20 | cout << minDiff; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /201712-2游戏.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | // 先将编号全放入队列,每次从头部取编号报数。若被淘汰,直接删去;若未淘汰,放到最后 7 | int main(int argc, char const *argv[]) 8 | { 9 | int n, k; 10 | cin >> n >> k; 11 | int count = 1; 12 | queue qi; 13 | for(int i = 0; i < n; i++) { 14 | qi.push(i + 1); 15 | } 16 | while(qi.size() > 1) { 17 | int num = qi.front(); 18 | qi.pop(); 19 | if(count % k == 0 || count % 10 == k) { 20 | } else { 21 | qi.push(num); 22 | } 23 | count++; 24 | } 25 | cout << qi.front(); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /201712-3Crontab.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | // 注意不区分大小写!! 12 | // 思路:首先根据crontab处理字符串,找出各单独参数minute, hour等可取的值,为避免重复,放入set中。 13 | // 之后有两种方法,一种是遍历从开始时间s到结束时间e的所有datetime,看其各元素是否在对应的set中, 14 | // 因为分钟数太多超时; 另一种是将各set元素组合,再加上可行的year,看星期数是否能对上, 15 | // 以及datetime是否在s,e之间 16 | 17 | string monStr[13] = {"", "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"}; 18 | string dayStr[7] = {"sun", "mon", "tue", "wed", "thu", "fri", "sat"}; 19 | int daysOfMon[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 20 | map monTab, dayTab; // "jan" -> 1, "sun" -> 0 21 | void build_table(); // 记录月份字符对应哪个月,星期字符对应星期几 22 | enum CronType {Minute, Hour, Date, Month, Day}; 23 | map > output; 24 | 25 | // 全转为小写 26 | void all_to_lower(string &s); 27 | // 字符转为整数 28 | int str_to_int(string &s); 29 | // 整数转为字符,整数为1位时补前导0 30 | string int_to_str(int x); 31 | // "Jan", "Sun", "1"等转为对应整数 32 | int timestr_to_int(CronType tag, string &str); 33 | // 根据CronType,将"*", "1,3", "1-3", "Sat"等转化成可以取到的值的set 34 | set cronstr_to_set(string &str, CronType tag); 35 | // 判断是否为闰年 36 | bool is_leap(int year); 37 | // 计算某天为星期几,0-6 38 | int calcDay(int year, int month, int date); 39 | 40 | int main(int argc, char const *argv[]) 41 | { 42 | build_table(); 43 | int n; 44 | string s, e; 45 | cin >> n >> s >> e; 46 | string syy = s.substr(0, 4), eyy = e.substr(0, 4); 47 | int syInt = str_to_int(syy), eyInt = str_to_int(eyy); 48 | while(n--) { 49 | string minute, hour, date, month, day, cmd; 50 | cin >> minute >> hour >> date >> month >> day >> cmd; 51 | set minutes = cronstr_to_set(minute, Minute); 52 | set hours = cronstr_to_set(hour, Hour); 53 | set dates = cronstr_to_set(date, Date); 54 | set months = cronstr_to_set(month, Month); 55 | set days = cronstr_to_set(day, Day); 56 | int curYear = syInt; 57 | while(curYear <= eyInt) { 58 | daysOfMon[2] = is_leap(curYear) ? 29 : 28; 59 | for(set::iterator ii = months.begin(); ii != months.end(); ii++) { 60 | int curMonth = *ii; 61 | for(set::iterator ji = dates.begin(); ji != dates.end(); ji++) { 62 | int curDate = *ji; 63 | int curDay = calcDay(curYear, curMonth, curDate); 64 | // 星期不匹配或超出天数时失败 65 | if(days.find(curDay) == days.end() || curDate > daysOfMon[curMonth]) continue; 66 | for(set::iterator ki = hours.begin(); ki != hours.end(); ki++) { 67 | for(set::iterator li = minutes.begin(); li != minutes.end(); li++) { 68 | string datetime = int_to_str(curYear) + int_to_str(curMonth) + 69 | int_to_str(curDate) + int_to_str(*ki) + int_to_str(*li); 70 | if(s <= datetime && datetime < e) { // 判断时间是否生效直接用字符串比较 71 | output[datetime].push_back(cmd); 72 | } 73 | } 74 | } 75 | } 76 | } 77 | curYear++; 78 | } 79 | } 80 | for(map >::iterator it = output.begin(); it != output.end(); it++) { 81 | for(int i = 0; i < it->second.size(); i++) { 82 | cout << it->first << " " << it->second[i] << endl; 83 | } 84 | } 85 | return 0; 86 | } 87 | 88 | void build_table() { 89 | for(int i = 1; i <= 12; i++) { 90 | monTab[monStr[i]] = i; 91 | } 92 | for(int i = 0; i < 7; i++) { 93 | dayTab[dayStr[i]] = i; 94 | } 95 | } 96 | 97 | int str_to_int(string &s) { 98 | stringstream ss(s); 99 | int res; 100 | ss >> res; 101 | return res; 102 | } 103 | 104 | string int_to_str(int x) { 105 | stringstream ss; 106 | ss << x; 107 | string res = ss.str(); 108 | if(res.size() == 1) res = "0" + res; 109 | return res; 110 | } 111 | 112 | void all_to_lower(string &s) { 113 | for(int i = 0; i < s.size(); i++) { 114 | s[i] = tolower(s[i]); 115 | } 116 | } 117 | 118 | int timestr_to_int(CronType tag, string &str) { 119 | if(tag == Month && isalpha(str[0])) { // 月份"Jan"等 120 | all_to_lower(str); 121 | return monTab[str]; 122 | } else if(tag == Day && isalpha(str[0])) { // 星期"Sun"等 123 | all_to_lower(str); 124 | return dayTab[str]; 125 | } else { 126 | return str_to_int(str); 127 | } 128 | } 129 | 130 | set cronstr_to_set(string &str, CronType tag) { 131 | set si; 132 | if(str == "*") { 133 | switch (tag) { 134 | case Minute: str = "0-59"; break; 135 | case Hour: str = "0-23"; break; 136 | case Date: str = "1-31"; break; 137 | case Month: str = "1-12"; break; 138 | case Day: str = "0-6"; break; 139 | default: break; 140 | } 141 | } 142 | str += ","; 143 | size_t comma = str.find(","); 144 | while(comma != string::npos) { 145 | string seg = str.substr(0, comma); // 按,截取 146 | size_t hyphen = seg.find("-"); 147 | if(hyphen == string::npos) { // 无-,离散值 148 | si.insert(timestr_to_int(tag, seg)); 149 | } else { // 有-,连续值 150 | string before = seg.substr(0, hyphen); 151 | string after = seg.substr(hyphen + 1, seg.size() - hyphen - 1); 152 | int from = timestr_to_int(tag, before), to = timestr_to_int(tag, after); 153 | while(from <= to) { 154 | si.insert(from); 155 | from++; 156 | } 157 | } 158 | str = str.substr(comma + 1, str.size() - comma - 1); 159 | comma = str.find(","); 160 | } 161 | return si; 162 | } 163 | 164 | inline bool is_leap(int year) { 165 | return (year % 400 == 0) || (year % 100 && year % 4 == 0); 166 | } 167 | 168 | // 19700101为周四,计算从该天开始经过了多少天 169 | int calcDay(int year, int month, int date) { 170 | int count = 0, curYear = 1970, curMon = 1; 171 | while(curYear < year) { 172 | count += is_leap(curYear) ? 2 : 1; // 365 % 7 = 1 173 | curYear++; 174 | } 175 | // 计算时本年二月已修正 176 | while(curMon < month) { 177 | count += daysOfMon[curMon]; 178 | curMon++; 179 | } 180 | count += date - 1; 181 | return (4 + count) % 7; 182 | } 183 | -------------------------------------------------------------------------------- /201803-1跳一跳.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | int main(int argc, char const *argv[]) 5 | { 6 | int sum = 0, last = 0, score; 7 | while(cin >> score) { 8 | switch (score) 9 | { 10 | case 0: 11 | cout << sum; 12 | return 0; 13 | case 1: 14 | sum += 1; 15 | last = 1; 16 | break; 17 | case 2: 18 | if(last == 1) { 19 | last = 2; 20 | } else { 21 | last += 2; 22 | } 23 | sum += last; 24 | break; 25 | default: 26 | break; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /201803-2碰撞的小球.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | // 。。。辣鸡csp,c++11都用不了 5 | // 将1s内的所有运动分解成一个一个球的运动,先运动的球到某个位置,记录该位置上有哪个球, 6 | // 后运动的球如果也到该位置,则检测到碰撞,一起变向 7 | struct ball { 8 | int pos; 9 | int speed; 10 | }; 11 | 12 | int main(int argc, char const *argv[]) 13 | { 14 | int n, l, t; 15 | cin >> n >> l >> t; 16 | vector balls; 17 | vector filled; // filled[i]表示位置i上球的编号,-1时无球 18 | for(int i = 0; i < l + 1; i++) { 19 | filled.push_back(-1); 20 | } 21 | int pos; 22 | for(int i = 0; i < n; i++) { 23 | cin >> pos; 24 | balls.push_back(ball{pos, 1}); 25 | } 26 | for(int i = 0; i < t; i++) { 27 | for(int j = 0; j < n; j++) { 28 | ball &ba = balls[j]; 29 | filled[ba.pos] = -1; 30 | if(ba.pos == 0 || ba.pos == l) { // 在两端时变向 31 | ba.speed *= -1; 32 | } 33 | int next = ba.pos + ba.speed; 34 | ba.pos = next; 35 | if(filled[next] >= 0) { // 检测到碰撞,两个都变向 36 | ba.speed *= -1; 37 | balls[filled[next]].speed *= -1; 38 | } else { 39 | filled[next] = j; 40 | } 41 | } 42 | } 43 | for(int i = 0; i < n; i++) { 44 | cout << balls[i].pos << " "; 45 | } 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /201803-3URL映射.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | // 注意大坑!!!URL末尾的斜杠要加入考虑, 7 | // 即/articles//与/articles/2003,/articles/与/articles/2003/均不匹配 8 | // c++用的不熟,有的处理挺蠢的 9 | struct Rule { 10 | string name; 11 | vector params; 12 | vector matches; 13 | }; 14 | 15 | void get_rules(vector &vr, int n); 16 | 17 | bool match(string &url, Rule &rule); 18 | 19 | int main(int argc, char const *argv[]) { 20 | int n, m; 21 | vector vr; 22 | cin >> n >> m; // n rule条数,m URL个数 23 | get_rules(vr, n); 24 | string url; 25 | vector urls; 26 | for(int i = 0; i < m; i++) { 27 | cin >> url; 28 | urls.push_back(url); 29 | } 30 | for(int i = 0; i < m; i++) { 31 | bool matched = false; 32 | for(int j = 0; j < n; j++) { // 依次对比规则 33 | Rule rule = vr[j]; 34 | if(match(urls[i], rule)) { 35 | matched = true; 36 | cout << rule.name; 37 | for(int k = 0; k < rule.matches.size(); k++) { 38 | cout << " " + rule.matches[k]; 39 | } 40 | rule.matches.clear(); 41 | break; 42 | } else { 43 | rule.matches.clear(); 44 | } 45 | } 46 | if(!matched) { 47 | cout << "404"; 48 | } 49 | cout << endl; 50 | } 51 | return 0; 52 | } 53 | 54 | // 根据'/'将规则split成params,/a//划成{"a", "", ""} 55 | // 注意后面的空string用来处理边界情况 56 | // start记录param的起点,由于url起点都为'/',start从1开始 57 | void get_rules(vector &vr, int n) { 58 | for(int i = 0; i < n; i++) { 59 | string rule, name; 60 | int start = 1, num = 0; 61 | cin >> rule >> name; 62 | vector params; 63 | for(int j = 1; j < rule.size(); j++) { 64 | if(rule[j] == '/') { 65 | params.push_back(rule.substr(start, num)); 66 | start += num + 1; 67 | num = 0; 68 | } else { 69 | num++; 70 | } 71 | } 72 | if(num > 0) { 73 | params.push_back(rule.substr(start, num)); 74 | } else { 75 | params.push_back(""); 76 | } 77 | vr.push_back(Rule {name, params, vector()}); 78 | } 79 | } 80 | 81 | // 判断url是否能与rule匹配 82 | bool match(string &url, Rule &rule) { 83 | int start = 1, n = url.size(); 84 | for(int j = 0; j < rule.params.size(); j++) { 85 | int i = start, num = 0; 86 | string param = rule.params[j]; 87 | if(param.empty()) { // rule结尾有'/' 88 | return i == n; // i==n时,url结尾也有'/';in,url结尾无'/' 89 | } else { 90 | bool flag = true; // 当不是path/int/str时不输出 91 | if(param == string("")) { // 取到末尾 92 | while(i < n) { 93 | i++; num++; 94 | } 95 | } else if(param == string("")) { 96 | while(i < n && url[i] != '/') { 97 | if(url[i] > '9' || url[i] < '0') { // 匹配失败 98 | return false; 99 | } else if(num == 0 && url[i] == '0' && i < n - 1) { 100 | start++; i++; 101 | } else { 102 | i++; num++; 103 | } 104 | } 105 | } else if(param == string("")) { 106 | while(i < n && url[i] != '/') { 107 | i++; num++; 108 | } 109 | } else { 110 | int pi = 0, np = param.size(); // 从param的pi位置遍历 111 | while(i < n && url[i] != '/') { 112 | if(pi >= np || param[pi] != url[i]) return false; 113 | pi++; i++; num++; 114 | } 115 | if(pi < np) return false; // url长度不够匹配 116 | flag = false; 117 | } 118 | if(num > 0) { 119 | if(flag) rule.matches.push_back(url.substr(start, num)); 120 | start += num + 1; 121 | } else { 122 | return false; 123 | } 124 | } 125 | } 126 | return start > n; // 当start>n,即params已匹配完,而url也刚好遍历完,匹配成功 127 | } 128 | //6 5 129 | ///articles/2003/ special_case_2003 130 | ///articles/ no_year_archive 131 | ///articles// year_archive 132 | ///articles/// month_archive 133 | ///articles//// article_detail 134 | ///static/ static_serve 135 | ///articles/2001 136 | ///articles/2004/ 137 | ///articles/1985/09/aloha/ 138 | ///articles/hello/ 139 | ///static/js/jquery.js 140 | 141 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CCF CSP认证 --------------------------------------------------------------------------------