RC-u1 热҈热҈热҈
分数 10
热҈热҈热҈……最近热得打的字都出汗了!
幸好某连锁餐厅开启了气温大于等于 35 度即可获得一杯免费雪碧的活动。但不知为何,在每个星期四的时候,这个活动会暂停一天……
现在给定连续的若干天的气温情况以及给定的第一天是星期几,请你算出有多少天你可以喝到免费的雪碧,又有多少天是因为星期四而导致你喝不到雪碧的。
输入格式:
输入第一行是两个正整数 N, W (1≤N≤50,1≤W≤7),表示给定连续的 N 天,下面给定的第一天是星期 W(7 等于星期天)。
接下来的一行给出 N 个用一个空格隔开的、小于 60 的整数,第 i 个数表示第 i 天的温度。保证温度大于等于 -273 度。
输出格式:
输出两个数,第一个是你能喝到免费雪碧的天数,第二个是你本来能喝到免费雪碧、但因为是星期四而无法喝到的天数。
输入样例:
15 3
33 35 34 36 37 40 32 31 30 29 28 29 33 38 40
AC代码,一周7天当是周日的时候,把k == 0就ok
#include<bits/stdc++.h>
using namespace std;
int main(){
int n, k;
cin >> n >> k;
if(k == 7)
k = 0;
int cnt1 = 0, cnt2 = 0;
for(int i = k; i < n + k; i++){
int x;
cin >> x;
if(x >= 35){
cnt1++;
if(i % 7 == 4)
cnt2 ++;
}
}
cout << cnt1 - cnt2 << " " << cnt2;
return 0;
}
RC-u2 谁进线下了?
分数 15
Xepa Legends 是一个第一人称射击类大逃杀(“吃鸡”)游戏,每轮游戏共有 20 支 3 人小队参加,最后获胜的队伍被称为“捍卫者”。
最近 Xepa Legends 举行了亚太地区南赛区的线上比赛,争夺 7 个前往德国曼海姆参加线下赛的资格,国内共有 14 支队伍参与到了其中。因为比赛十分激烈,直到最后谁进了线下仍有巨大的疑问。小 K 喜欢的国内知名战队 DreamTear 因其队内选手杀马特表现不佳,正好卡在出线分数前后,请你赶紧帮帮小 K,计算一下最后的分数情况,看看他喜欢的战队出线了没有吧!
Xepa Legends 的比赛共进行 N 场游戏,在每场游戏中,每支队伍在游戏中会获得一个排名和一个杀敌数(击败其他队伍玩家的数量),一支队伍在一场游戏的得分为杀敌数+排名分,排名分由队伍当场的排名根据以下表格求得:
排名 | 分数 |
---|---|
第一名 | 12 分 |
第二名 | 9 分 |
第三名 | 7 分 |
第四名 | 5 分 |
第五名 | 4 分 |
第六名至第七名 | 3 分 |
第八名至第十名 | 2 分 |
第十一名至第十五名 | 1 分 |
第十六名至第二十名 | 0 分 |
例如,
- DreamTear 战队在第三场比赛获得了第三名、有 6 个杀敌数,那么他们将获得 7 + 6 = 13 分;
- KV 战队在第二场比赛获得了第 19 名、有 1 个杀敌数,那么他们将获得 0 + 1 = 1 分;
- SRN 战队在第四场比赛获得了第 1 名、有 9 个杀敌数,那么他们将获得 12 + 9 = 21 分。
注:本题与实际情况无关,所有比赛规则、队伍、队员名称均为虚构。
输入格式:
输入第一行是一个正整数 N (≤20),表示有 N 场比赛。
接下来有 N 部分输入,每部分是一场比赛的情况。对每一场比赛,信息共分 20 行,第 i 行(i=1,⋯,20)给出的两个非负整数 p 和 k 表示第 i 支队伍在这场比赛里获得了第 p 名、杀敌数为 k。
数据保证所有给定的情况中,排名永远大于等于 1 且小于等于 20,杀敌数小于等于 57。
输出格式:
输出 20 行,按编号从小到大依次输出队伍的编号及该队全部游戏结束时的总分。
输入样例:
3
6 2
7 3
11 5
10 1
2 9
5 8
14 3
4 3
1 6
18 1
12 1
20 0
13 0
3 2
16 4
8 1
19 0
9 4
17 1
15 0
8 2
19 1
12 2
1 9
10 1
7 5
18 0
14 0
5 2
4 4
2 5
6 2
16 3
13 1
20 0
3 7
9 3
15 0
17 5
11 3
18 0
5 2
2 9
9 4
4 7
10 3
16 0
1 6
20 0
15 1
6 0
3 6
14 3
7 4
19 0
17 0
8 9
11 0
13 5
12 0
输出样例:
1 9
2 13
3 27
4 30
5 33
6 25
7 4
8 27
9 24
10 12
11 19
12 18
13 8
14 18
15 4
16 17
17 16
18 8
19 12
20 6
把对应元素相加即可
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin >> n ;
vector<int> v = {12, 9, 7, 5, 4, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1};
v.resize(20);
vector<pair<int,int>> s(20);
for(int i = 0; i < n; i ++){
for(int j = 0; j < 20; j ++){
int a, b;
cin >> a >> b;
s[j].first += (v[a - 1] + b);
s[j].second = j;
}
}
for(auto [x, y] : s){
cout << y + 1 << " " << x << endl;
}
return 0;
}
RC-u3 暖炉与水豚
PapiCon(@PapilloteContet)出了许多有意思的谜题,其中有一道关于水豚的谜题是这样的:
来源:x.com/PapilloteContet
在一个 N×M 的矩阵中有若干水豚以及暖炉,暖炉可以辐射以它自身为中心的 3×3 范围里的水豚,使其变得暖呼呼的。谜题里存在一只冷的要命的水豚,你需要移动其中的一个暖炉,使所有水豚都变得暖呼呼的。
在往下读题前,如果你有兴趣的话,不妨思考一下如何解答这个谜题。(思考结果与题目无关,可跳过。)
这个谜题的关键在于,单纯从图中能看到的暖炉来说是无解的,但如果注意到,第 3 行第 6 列的水豚明明周围没有暖炉,却也处于暖呼呼的状态,就能推测出来图中的那个对话框挡住了一个暖炉,只要移动这个暖炉就可以完成题目的要求。
现在我们将谜题一般化,对于给定的一个 N×M 的矩阵、对应的所有水豚状态、以及能看到的暖炉摆放情况,已知最多只有一只水豚的状态不太对劲(周围没有暖炉却暖呼呼的),你需要推测有哪些格子可能藏了暖炉。一个空格可能藏了暖炉可以理解为:当前空格设置暖炉后整个矩阵的状态会从不合法变为合法。
输入格式:
输入第一行是两个正整数 N, M (1≤N,M≤1000),表示矩阵的大小。
接下来的 N 行,每行有 M 个字符,第 i 行的第 j 个字符表示矩阵中对应位置的状态,其中:
.
表示空格(或者说,看上去是空格的格子);c
表示很冷的水豚;w
表示暖呼呼的水豚;m
表示暖炉。
输出格式:
输出若干行,每行两个正整数 r 和 c,表示第 r 行第 c 列有可能藏了一个暖炉,有多个可能时,先按 r 从小到大输出,r 相同时再按 c 从小到大输出。如果没有一个格子可能藏了暖炉, 则在一行中输出Too cold!
。
行与列均从 1 开始编号。
输入样例:
6 8
wm....mw
.w..ww..
..wm.wwm
w.w....w
.m.c.m..
w.....w.
输出样例:
2 7
3 5
4 6
4 7
题目只说当只有w的时候只有异常,通过c可以确定剩下暖壶可能存在的位置,再判断w的是否合法
#include<bits/stdc++.h>
using namespace std;
int main(){
int n, m;
cin >> n >> m;
vector<vector<char>> v(n, vector<char>(m));
int xx[8] = {0, 0, -1, 1, -1, -1, 1, 1 };
int yy[8] = {-1, 1, 0, 0, -1, 1, -1, 1 };
for(int i = 0; i < n; i ++){
for(int j = 0; j < m; j ++)
cin >> v[i][j];
}
for(int i = 0; i < n; i ++){
for(int j = 0; j < m; j ++){
if(v[i][j] == 'c'){
for(int k = 0; k < 8; k ++){
int x = i + xx[k];
int y = j + yy[k];
if(x >= 0 && x < n && y >= 0 && y < m && v[x][y] == '.')
v[x][y] = 'o';
}
}
}
}
vector<pair<int, int>> res;
for(int i = 0; i < n; i ++){
for(int j = 0; j < m; j ++){
if(v[i][j] == 'w'){
for(int k = 0; k < 8; k ++){
int x = i + xx[k];
int y = j + yy[k];
if(x >= 0 && x < n && y >= 0 && y < m){
if(v[x][y] == '.')
res.push_back({x, y});
else if(v[x][y] == 'm'){
res.clear();
break;
}
}
}
if(res.size()){
sort(res.begin(), res.end());
for(auto [x, y] : res)
cout << x + 1<< " " << y + 1<< endl;
return 0;
}
}
}
}
cout << "Too cold!";
return 0;
}
RC-u4 章鱼图的判断
对于无向图 G=(V,E),我们将有且只有一个环的、大于 2 个顶点的无向连通图称之为章鱼图,因为其形状像是一个环(身体)带着若干个树(触手),故得名。
给定一个无向图,请你判断是不是只有一个章鱼子图存在。
输入格式:
输入第一行是一个正整数 T (1≤T≤5),表示数据的组数。
每组数据的第一行是两个正整数 N,M (1≤N,M≤105),表示给定的无向图有 N 个点,M 条边。
接下来的 M 行,每行给出一条边两个端点的顶点编号。注意:顶点编号从 1 开始,并且题目保证任何边不会重复给出,且没有自环。
输出格式:
对于每组数据,如果给定的图里只有一个章鱼子图,则在一行中输出 Yes
和章鱼子图环的大小(及环中顶点数),其间以 1 个空格分隔。
否则,则在一行中输出 No
和图中章鱼子图的个数,其间以 1 个空格分隔。
输入样例:
3
10 10
1 3
3 5
5 7
7 9
1 2
2 4
2 6
3 8
9 10
1 9
10 10
1 3
3 5
5 7
7 9
9 1
1 2
2 4
4 8
8 10
10 1
10 10
1 3
3 5
5 7
7 9
9 1
2 4
4 8
8 10
10 2
10 6
输出样例:
Yes 5
No 0
No 2
把路径记录下来,当找到一个已经被遍历的node,只要这个node不是路径的上一个点,只要是如图所示的环就没有问题,当一个图中可能存在两个环,需要判断一下,但只得到17分,求高手指点
#include<bits/stdc++.h>
using namespace std;
#define pd push_back
#define ppb pop_back
void solve(){
int n, m;
cin >> n >> m;
vector<vector<int>> v(n + 1);
for(int i = 0; i < m; i ++){
int a, b;
cin >> a >> b;
v[a].pd(b);
v[b].pd(a);
}
vector<int> path;
vector<int> res;
vector<bool> st(n + 1, false);
auto check = [&](int x) -> int{
int len = path.size();
for(int j = 0; j < len - 2; j ++){
if(path[j] == x)
return j;
}
return -1;
};
function<void(int, vector<int>&)> dfs = [&](int a, vector<int> &path) -> void{
path.pd(a);
st[a] = true;
int l = v[a].size();
for(int i = 0; i < l; i ++){
int len = path.size();
if(st[v[a][i]] && len > 1 && path[len - 2] != v[a][i]){
int t = check(v[a][i]);
// if(t != 0)
res.pd(path.size() - t);
}else if(!st[v[a][i]]){
dfs(v[a][i], path);
}
}
path.ppb();
return ;
};
for(int i = 1; i <= n; i ++){
if(!st[i]){
int t = res.size();
dfs(i, path);
if(res.size() - t > 1)
res.erase(res.begin() + t, res.end());
}
}
if(res.size() == 1)
cout << "Yes" << " " << res[0] << endl;
else{
cout << "No" << " ";
cout << res.size() << endl;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
for(int i = 0; i < n; i ++)
solve();
return 0;
}
RC-u5 工作安排
小 K 有 N 项工作等待完成,第 i 项工作需要花 ti 单位时间,必须在 di 时刻或之前完成,报酬为 pi。假设小 K 工作时刻从 0 开始,且同一时刻只能做一项工作、工作一旦开始则不可中断或切换至其他工作,请你帮小 K 规划一下如何选择合适的工作,使小 K 可以获得最多的报酬。
输入格式:
输入第一行是一个正整数 T (≤5),表示数据的组数。
接下来有 T 组数据,每组数据第一行是一个正整数 N (≤5000),表示待完成工作的数量。接下来的 N 行,每行三个非负整数 ti、di、pi (均 ≤5000;1≤i≤N),表示第 i 项工作需要花费的时间、截止时间以及报酬。
输出格式:
对于每组数据,输出小 K 能获得最多的报酬是多少。
输入样例:
3
5
1 2 50
3 3 100
1 5 1
3 2 5000
4 5 30
5
1 2 50
3 3 20
1 5 1
3 2 5000
4 5 30
5
1 2 50
3 3 100
1 5 1
3 2 5000
5 5 800
输出样例:
101
80
800
一眼dp,状态是时间,但需要对截止时间从小到大进行排序,否则会稍加,达不到最优条件
如果不进行排序,那么如果红色部分在前面,则蓝色部分的值就会舍弃,不知最优结果
#include <bits/stdc++.h>
using namespace std;
#define MAX_TIME 5000
struct Job {
int t; // 花费时间
int d; // 截止时间
int p; // 报酬
Job(int t, int d, int p) : t(t), d(d), p(p) {}
};
void solve() {
int n;
cin >> n;
vector<Job> jobs;
for (int i = 0; i < n; ++i) {
int t, d, p;
cin >> t >> d >> p;
jobs.emplace_back(t, d, p);
}
// 按截止时间升序排序
sort(jobs.begin(), jobs.end(), [](const Job& a, const Job& b) {
return a.d < b.d;
});
// dp数组初始化
vector<int> dp(MAX_TIME + 1, 0);
// 处理每个工作
for (const auto& job : jobs) {
int t = job.t;
int d = job.d;
int p = job.p;
// 逆序更新dp数组,确保每个工作只被考虑一次
for (int j = d; j >= t; --j) {
dp[j] = max(dp[j], dp[j - t] + p);
}
}
// 计算最大报酬
int max_profit = *max_element(dp.begin(), dp.end());
cout << max_profit << endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}