2024年6月CSP,回顾+题解。
等题目出来后补充题解。
回顾
整体相较上次有进步,题目变难了一点点,得分360/500。
第一、二题比较容易,花了20分钟过掉了。
第三题大模拟花了两个多小时,只拿了40分,剩下的点全部MLE了,考场上以为是自己的问题,回来看榜发现全国只有6个人过掉了大模拟QuQ,谁家正经考试把压轴放正中间啊QuQ。
然后看完了四五题题目,发现第五题考察的似乎是一个二维的区间最值问题,感觉过不掉,遂打了一个暴力,拿20分。(感觉再做做优化一下也可以多拿点)
第四题动态规划,分组背包,抢着在最后40分钟过掉了,保住了300分。
Conclusion:第三题太抽象。
题解
A. 矩阵重塑(其一)
题意:给一个 n * m 大小矩阵,用 p * q 的大小重新排布矩阵。
分析:用一维数组接收,改变输出格式即可。
完整代码:
| 12
 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)。
完整代码:
| 12
 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. 货物调度
考点:分组背包,贪心。
完整代码:
| 12
 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;
 }
 
 | 
成绩
