第34次CCF_CSP认证

2024年6月CSP,回顾+题解。

等题目出来后补充题解。

回顾

整体相较上次有进步,题目变难了一点点,得分360/500

第一、二题比较容易,花了20分钟过掉了。

第三题大模拟花了两个多小时,只拿了40分,剩下的点全部MLE了,考场上以为是自己的问题,回来看榜发现全国只有6个人过掉了大模拟QuQ,谁家正经考试把压轴放正中间啊QuQ。

然后看完了四五题题目,发现第五题考察的似乎是一个二维的区间最值问题,感觉过不掉,遂打了一个暴力,拿20分。(感觉再做做优化一下也可以多拿点)

第四题动态规划,分组背包,抢着在最后40分钟过掉了,保住了300分。

Conclusion:第三题太抽象。

题解

A. 矩阵重塑(其一)

题意:给一个 n * m 大小矩阵,用 p * q 的大小重新排布矩阵。

分析:用一维数组接收,改变输出格式即可。

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<bits/stdc++.h>
#define int long long
using namespace std;

inline int read(){
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
return x * f;
}

signed main(){
int n = read(), m = read(), p = read(), q = read();
vector<int>v(n * m);
for(auto &i : v) i = read();
for(int i = 0; i < p; i ++){
for(int j = 0; j < q; j++){
cout << v[i * q + j] << ' ';
}
puts("");
}
return 0;
}

B. 矩阵重塑(其二)

题意:实现 查询、重塑、转置 三个操作。(转置操作不超过100次)

分析:依然使用一维数组接收,查询操作O(1),重塑操作只要改变记录的行列数即可,O(1),题目告诉我们转置操作次数很少,直接暴力给数组重新按转置的方式赋值即可,O(mn)

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include<bits/stdc++.h>
#define int long long
using namespace std;

inline int read(){
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
return x * f;
}

signed main(){
int n = read(), m = read(), t = read();
vector<int>v(n * m);
for(auto &i : v) i = read();
while(t--){
int op = read(), a = read(), b = read();
if(op == 1){
n = a, m = b;
}
else if(op == 2){
vector<int>tmp(n * m);
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++){
tmp[j * n + i] = v[i * m + j];
}
}
v = tmp;
swap(n, m);
}
else{
cout << v[a * m + b] << '\n';
}
}

return 0;
}

D. 货物调度

考点:分组背包,贪心。

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include<bits/stdc++.h>
#define int long long
using namespace std;

inline int read(){
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
return x * f;
}

const int N = 1005, M = 1e4;
int b[N], c[N];
int a[N][N], sz[N], d[N][N], dp[M];

bool cmp(int x, int y){
return x > y;
}

signed main(){
int n = read(), m = read(), v = read();
for(int i = 0; i < n; i++){
b[i] = read(), c[i] = read();
}
for(int i = 0; i < m; i++){
int w = read(), t = read();
a[t][sz[t]++] = w;
}
for(int i = 0; i < n; i++) sort(a[i], a[i] + sz[i], cmp);

for(int i = 0; i < n; i++){
for(int j = 1; j < sz[i]; j++){
a[i][j] += a[i][j - 1];
}
}

for(int i = 0; i < n; i++){
for(int j = 0; j < sz[i]; j++){
d[i][j] = (j + 1) * c[i] + b[i];
a[i][j] -= d[i][j];
}
}

for(int i = 0; i < n; i++){
for(int j = M - 1; j >= 0; j--){
for(int k = 0; k < sz[i]; k++){
if(d[i][k] <= j)
dp[j] = max(dp[j], dp[j - d[i][k]] + a[i][k]);
}
}
}

int mn = 0;
for(int i = 0; i < M; i++){
if(dp[i] >= v){
mn = i;
break;
}
}
cout << mn;
return 0;
}

成绩