SUST_ACM_2019届暑期ACM集训热身赛题解

时间:2022-12-20 13:04:36

问题A:Hello SUST!

知识点:基本输入输出

C/C++:

SUST_ACM_2019届暑期ACM集训热身赛题解SUST_ACM_2019届暑期ACM集训热身赛题解
 1 #include <stdio.h>
 2 
 3 int main() {
 4     int n;
 5     scanf("%d", &n);
 6     while(n --) {
 7         printf("Hello SUST!\n");
 8     }
 9     return 0;
10 }
View Code

问题B:计算A+B

知识点:基本输入输出

C/C++:

SUST_ACM_2019届暑期ACM集训热身赛题解SUST_ACM_2019届暑期ACM集训热身赛题解
1 #include <cstdio>
2 
3 int main() {
4     int a, b;
5     while(~scanf("%d %d", &a, &b)) {
6         printf("%d\n", a + b);
7     }
8     return 0;
9 }
View Code

问题C:

知识点:基本输入输出

C/C++:

SUST_ACM_2019届暑期ACM集训热身赛题解SUST_ACM_2019届暑期ACM集训热身赛题解
1 #include <cstdio>
2 
3 int main() {
4     int n;
5     while(scanf("%d", &n) && n) {
6         printf("%d\n", n * (n + 1) / 2);
7     }
8     return 0;
9 }
View Code

问题D:

知识点:递推

C/C++:

SUST_ACM_2019届暑期ACM集训热身赛题解SUST_ACM_2019届暑期ACM集训热身赛题解
 1 #include <cstdio>
 2 using namespace std;
 3 
 4 const int maxn = 20 + 5;
 5 typedef long long ll;
 6 ll ans[maxn];
 7 int t, n;
 8 
 9 int main() {
10     ans[0] = ans[1] = 1;
11     for(int i = 2; i < maxn; i ++) {
12         ans[i] = ans[i - 1] + ans[i - 2];
13     }
14     scanf("%d", &t);
15     while(t --) {
16         scanf("%d", &n);
17         printf("%lld\n", ans[n]);
18     }
19     return 0;
20 }
View Code

问题E:

知识点:排序

C/C++:

SUST_ACM_2019届暑期ACM集训热身赛题解SUST_ACM_2019届暑期ACM集训热身赛题解
 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 const int maxn = 10 + 5;
 6 double score[maxn];
 7 
 8 bool cmp(const double &a, const double &b) {
 9     return a > b;
10 }
11 
12 int main() {
13     int t, n, m;
14     scanf("%d", &t);
15     while(t --) {
16         scanf("%d %d", &n, &m);
17         for(int i = 0; i < n; i ++) scanf("%lf", &score[i]);
18         // sort(score, score + n, cmp);//可用冒泡排序代替
19         // /*
20             for(int i = 0; i < n - 1; i ++) {
21                 for(int j = 0; j < n - 1 - i; j ++) {
22                     if(score[j + 1] > score[j]) {
23                         double temp = score[j];
24                         score[j] = score[j + 1];
25                         score[j + 1] = temp;
26                     }
27                 }
28             }
29         // */
30         double ans = 0.0;
31         for(int i = 0; i < m; i ++) {
32             ans += score[i];
33         }
34         printf("%.2f\n", ans / m * 1.0);
35     }
36     return 0;
37 }
View Code

问题F:

知识点:循环语句和判断语句

C/C++:

SUST_ACM_2019届暑期ACM集训热身赛题解SUST_ACM_2019届暑期ACM集训热身赛题解
 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 char G[3][3];
 6 bool ans;
 7 
 8 int main() {
 9     int t, flag;
10     scanf("%d", &t);
11     while(t --) {
12         ans = false;
13         for(int i = 0; i < 3; i ++) {
14             scanf("%s", G[i]);
15         }
16         if((G[0][0] == '0' && G[1][1] == '0' && G[2][2] == '0') || (G[0][2] == '0' && G[1][1] == '0' && G[2][0] == '0'))
17             ans = true;//检查斜向true
18         if(!ans) {
19             for(int i = 0; i < 3; i ++) {
20                 flag = 0;
21                 for(int j = 0; j < 3; j ++) {
22                     if(G[i][j] == '0') flag ++;
23                 }
24                 if(flag == 3) {
25                     ans = true;
26                     break;
27                 }//检查横向
28                 flag = 0;
29                 for(int j = 0; j < 3; j ++) {
30                     if(G[j][i] == '0') flag ++;
31                 }//检查纵向
32                 if(flag == 3) {
33                     ans = true;
34                     break;
35                 }
36             }
37         }
38         if(ans) printf("Yes\n");
39         else printf("No\n");
40     }
41     return 0;
42 }
View Code

问题G:

知识点:字符串存储

C/C++:

SUST_ACM_2019届暑期ACM集训热身赛题解SUST_ACM_2019届暑期ACM集训热身赛题解
 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 char str[8][20] = {
 6     "Monday",
 7     "Tuesday",
 8     "Wednesday",
 9     "Thursday",
10     "Friday",
11     "Saturday",
12     "Sunday"
13 };
14 
15 int main() {
16     int n;
17     while(scanf("%d", &n) && n) {
18         if(n <= 7)
19             printf("%s\n", str[n - 1]);
20     }
21     return 0;
22 }
View Code

问题H:

知识点:循环语句

C/C++:

SUST_ACM_2019届暑期ACM集训热身赛题解SUST_ACM_2019届暑期ACM集训热身赛题解
 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 const int maxn = 100;
 6 int value[4] = {2, 3, 5, 10};
 7 bool vis[maxn];
 8 
 9 int main() {
10     int n;
11     for(int i = 0; i <= 2; i ++) {
12         for(int j = 0; j <= 2; j ++) {
13             for(int k = 0; k <= 2; k ++) {
14                 for(int p = 0; p <= 2; p ++) {
15                     vis[i * value[0] + j * value[1] + k * value[2] + p * value[3]] = true;
16                 }
17             }
18         }
19     }
20     while(scanf("%d", &n) && n) {
21         if(vis[n]) printf("Y\n");
22         else printf("N\n");
23     }
24     return 0;
25 }
View Code

问题I:

知识点:题目要判断三维空间内四个点是否共面,则只需知道由四个点组成的三个向量是否共面即可知道答案。

  我们知道两个向量a, b, 的向量积等于垂直于他们所在平面的空间向量c,如果c与另一个向量d垂直,那我们就可以证明a,b,c三向量共面。

  我们可以利用矩阵(行列式)计算出c向量,再与d进行点乘,判定结果是否为零即可(两向量平行,内积为零)。

C/C++:

SUST_ACM_2019届暑期ACM集训热身赛题解SUST_ACM_2019届暑期ACM集训热身赛题解
 1 #include <cstdio>
 2 #include <cstdlib>
 3 using namespace std;
 4 
 5 struct node{
 6     int x, y, z;
 7 } a[4], b[3];
 8 
 9 bool plane() {
10     bool ret = false;
11     if(b[0].x * (b[1].y * b[2].z - b[1].z * b[2].y) - b[1].x * (b[0].y * b[2].z - b[0].z * b[2].y) + b[2].x * (b[0].y * b[1].z - b[0].z * b[1].y) == 0)
12         ret = true;
13     return ret;
14 }
15 
16 int main()
17 {
18     int T, day = 1;
19     scanf("%d", &T);
20     while(T--) {
21         for(int i = 0; i < 4; i ++) {
22             scanf("%d %d %d", &a[i].x, &a[i].y, &a[i].z);
23         }
24         for(int i = 0; i < 3; i ++) {
25             b[i].x = a[i + 1].x - a[i].x;
26             b[i].y = a[i + 1].y - a[i].y;
27             b[i].z = a[i + 1].z - a[i].z;
28         }
29         if(plane())
30             printf("Day #%d: Yes\n", day);
31         else
32             printf("Day #%d: No\n", day);
33         day ++;
34     }
35     return 0;
36 }
View Code

问题J:

题意:

  从L走到C的最短路dist是否小于k?小于k的话从L到C路径长度等于dist的不全重复的路径有几条?

思路:

  由于DFS求解最短路之缓慢,所以我们可以先用BFS算出最短路,判断可行之后再用DFS求出满足条件的条数即可。在执行DFS时,我们先从起点出发,任意选择其中一条路并且一直走到不满足题解的状态时我们回退到上一个可以继续往前走的状态继续往前走,往前走的时候记得标记走过的路,往回走的时候记得取消标记,这样可以保证所有路都被找到并且没有重复,实现起来也比较简便。

C/C++:

SUST_ACM_2019届暑期ACM集训热身赛题解SUST_ACM_2019届暑期ACM集训热身赛题解
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 #include <cmath>
 5 using namespace std;
 6 
 7 typedef pair<int, int> pii;
 8 const int maxn = 1e3 + 5;
 9 int n, m, k, step, ans, Dist;
10 char G[maxn][maxn];
11 int dist[maxn][maxn];
12 bool vis[maxn][maxn];
13 pii B, E, now, Next;
14 /*
15     这里的pair完全可以用结构体代替
16 
17     pair<int, int> 可以看作是一个类似于结构体的寄存器
18     比如 struct P {
19         int first, second;
20     }now;
21     可以用now.first, now.second访问这个变量的两个值。
22     也可以申明pair<int, int>类型的数组,也就相当于struct P array[size];
23  */
24 int bfs(int x, int y) {
25     memset(vis, false, sizeof vis);
26     memset(dist, 0, sizeof dist);
27     queue <pii> Q;
28     Q.push(make_pair(x, y));
29     dist[x][y] = 0;
30     while(!Q.empty()) {
31         pii now = Q.front();
32         Q.pop();
33         if(now.first == E.first && now.second == E.second) return dist[now.first][now.second];
34         for(int dx = -1; dx <= 1; dx ++) {
35             for(int dy = -1; dy <= 1; dy ++) {
36                 if(abs(dx - dy) == 1) {
37                     Next.first = now.first + dx;
38                     Next.second = now.second + dy;
39                     if(!vis[Next.first][Next.second] && Next.first >= 0 && Next.first < n && Next.second >= 0 && Next.second < m && G[Next.first][Next.second] != '#') {
40                         dist[Next.first][Next.second] = dist[now.first][now.second] + 1;
41                         Q.push(make_pair(Next.first, Next.second));
42                         vis[Next.first][Next.second] = true;
43                     }
44                 }
45             }
46         }
47     }
48     return -1;
49 }
50 
51 void dfs(pii B, pii E, int D) {
52     if(B.first == E.first && B.second == E.second) {
53         if(D == ans) step ++;//如果当前访问的结点为终点且到起点的距离为最短路则step++
54     }
55     if(D > ans) return;//如果当前路径在D步内不能到达终点则回退,换下一条路
56     for(int i = -1; i <= 1; i ++) {
57         for(int j = -1; j <= 1; j ++) {
58             if(abs(i - j) == 1) {//由于只能从上下左右四个方向走,所以可以找出这样的关系式,读者可以自行在草稿纸上进行验证
59                 if(B.first + i >= 0 && B.first + i < n && B.second + j >= 0 && B.second + j < m) {//不越界
60                     if(G[B.first + i][B.second + j] != '#' && !vis[B.first + i][B.second + j]) {//判断是否没有访问过且不为石头
61                         vis[B.first + i][B.second + j] = true;
62                         dfs(make_pair(B.first + i, B.second + j), E, D + 1);//递归走下一步
63                         vis[B.first + i][B.second + j] = false;//记得修复状态
64                     }
65                 }
66             }
67         }
68     }
69 }
70 
71 int main() {
72     int t, Case = 0;
73     scanf("%d", &t);
74     while(t --) {
75         step = 0;
76         Dist = 0x3f3f3f3f;
77         scanf("%d %d %d", &n, &m, &k);
78         for(int i = 0; i < n; i ++) scanf("%s", G[i]);
79         for(int i = 0; i < n; i ++) {
80             for(int j = 0; j < m; j ++) {
81                 if(G[i][j] == 'L') B = make_pair(i, j);
82                 if(G[i][j] == 'C') E = make_pair(i, j);
83             }
84         }
85         ans = bfs(B.first, B.second);
86         if(ans > k) ans = -1;
87         printf("Case #%d: %d ", ++Case, ans);
88         if(ans != -1) {
89             memset(vis, false, sizeof vis);
90             dfs(B, E, 0);
91             printf("%d", step);
92         }
93         printf("\n");
94     }
95     return 0;
96 }
View Code