2020年天梯赛补题报告
L1-3调和平均 (10分)
这题用数组会被扣一分,不用数组就能做对,不知道为啥...
#include <bits/stdc++.h> using namespace std; int n; double res = 0; int main() { cin >> n; for(int i = 1;i <= n; ++ i){ double x; cin >> x; res += 1.0/x; } res /= (1.0 * n); res = 1.0 / res; printf("%.2lf", res); }
L1-6 吃火锅 (15分)
string里有一个 find() 函数挺好用的
#include <bits/stdc++.h> using namespace std; string str; int cnt = 0, flag = 0, s; int main() { while(getline(cin, str), str != ".") { cnt ++; int f = 0, vis = 0; while(f != -1) { f = str.find("chi1 huo3 guo1", f); if(f == -1) break; if(flag == 0) flag = cnt; if(vis == 0) vis = 1, s ++; f ++; } } if(flag == 0){ cout << cnt << endl; puts("-_-#"); return 0; } cout << cnt << endl; cout << flag << " " << s << endl; }
L1-8 刮刮彩票 (20分)
他没刮开的地方也要算进sum里。。。
#include <bits/stdc++.h> using namespace std; int s, a[10][10], sum[110] = {0, 0, 0, 0, 0, 0 , 10000, 36, 720, 360, 80, 252, 108, 72, 54, 180, 72, 180, 119, 36, 306, 1080, 144, 1800, 3600}; bool flag[10][10], vis[110]; int main() { for(int i = 1;i <= 3; ++ i){ for(int j = 1;j <= 3; ++ j){ cin >> a[i][j]; if(a[i][j] != 0){ vis[a[i][j]] = true; } else flag[i][j] = true; } } for(int i = 1;i <= 9; ++ i) if(!vis[i]) s = i; for(int i = 1;i <= 3; ++ i){ for(int j = 1;j <= 3; ++ j){ if(flag[i][j]) a[i][j] = s; } } for(int i = 0;i < 3; ++ i){ int x, y; cin >> x >> y; cout << a[x][y] << endl; flag[x][y] = true; } int k; cin >> k; s = 0; if(k >= 1 && k <= 3){ for(int i = 1;i <= 3; ++ i){ // if(flag[k][i]) s += a[k][i]; } } else if(k >= 4 && k <= 6){ for(int i = 1;i <= 3; ++ i){ // if(flag[i][k]) s += a[i][k - 3]; // 出大问题.... } } else if(k == 7){ for(int i = 1;i <= 3; ++ i){ // if(flag[i][i]) s += a[i][i]; // printf("a[%d][%d] = %d\n", i, i, a[i][i]); } } else{ for(int i = 1, j = 3;i <= 3; ++ i, -- j){ s += a[i][j]; } } // cout << s << endl; cout << sum[s] << endl; }
L2-2 口罩发放 (25分)
这题要注意一些细节,比如身份证号必须由18位的数字构成,有可能会有重名的,排序时不能打乱原来有序时的顺序(即相等的元素不能交换位置)
#include <bits/stdc++.h> using namespace std; const int N = 1010; struct node{ string name; string id; bool sick; int th, tm; int s; }a[N]; bool cmp(node a, node b) { int t1 = a.th * 60 + a.tm, t2 = b.th * 60 + b.tm; if(t1 == t2){ return a.s < b.s; } return a.th * 60 + a.tm < b.th * 60 + b.tm; } bool check(string str) { if(str.size() != 18) return false; for(int i = 0;i < str.size(); ++ i){ if(!isdigit(str[i])) return false; } return true; } int d, p, n, m, date, s; map<string, int> mp; vector<node> sick; int main() { cin >> d >> p; while(d --) { date ++; cin >> n >> m; for(int i = 1;i <= n; ++ i){ cin >> a[i].name >> a[i].id >> a[i].sick; s ++; a[i].s = s; scanf("%d:%d", &a[i].th, &a[i].tm); string id = a[i].id; if(a[i].sick && check(id)){ int f = 1; for(int j = 0;j < sick.size(); ++ j){ if(id == sick[j].id){ f = 0; break; } } if(f) sick.push_back(a[i]); } } sort(a + 1, a + 1 + n, cmp); int cnt = 0; for(int i = 1;i <= n; ++ i){ string id = a[i].id; if(check(id) && cnt < m && (mp[id] == 0 || (date - mp[id] >= p + 1))){ mp[id] = date; cout << a[i].name << " " << a[i].id << endl; cnt ++; } } } for(int i = 0;i < sick.size(); ++ i){ cout << sick[i].name << " " << sick[i].id << endl; } }
网红点打卡攻略 (25分)
需要注意的就是他说的 “在每个网红点打卡仅一次”, 所以如果两个网红点没有路时不能通过其它的网红点到达(好像可以通过家再到达另一个网红点,但测试样例中好像没有这种情况),剩下的就是按着他的方案来就行了。
#include <bits/stdc++.h> using namespace std; int n, m, k, sum, cnt, a[220][220]; bool vis[220]; pair<int, int> ans; int main() { ans.second = 0x3f3f3f3f; cin >> n >> m; while(m --) { int x, y, z; cin >> x >> y >> z; a[x][y] = z; a[y][x] = z; } cin >> k; while(k --) { memset(vis, 0, sizeof(vis)); cnt ++; int w; cin >> w; int tmp; cin >> tmp; vis[tmp] = true; int cost = 0, f = 1; if(a[0][tmp] == 0){ f = 0; } cost += a[0][tmp]; if(w != n) f = 0; for(int i = 2;i <= w; ++ i){ int x; cin >> x; if(vis[x]) f = 0; vis[x] = true; if(a[tmp][x] == 0) f = 0; else cost += a[tmp][x]; tmp = x; } if(a[tmp][0] == 0) f = 0; else cost += a[tmp][0]; if(f) sum ++; if(f && cost < ans.second){ ans.second = cost; ans.first = cnt; } } cout << sum << endl; cout << ans.first << " " << ans.second << endl; }