bistuacm新生训练赛第八场题解

    xiaoxiao2025-04-30  11

    第一次写题解和写博客,若有错误希望各位包容

    (由于对知识点的了解不多,可能不知道有的题的知识点是啥)

    A - Text Volume

    题意:

    输入一段文字,找出每一个单词的大写字母的个数,称为这个单词的量(?不知道该如何翻译),输出那个最大的单词的量。

    思路: 把输入的文本看作一个个字符,如果这个字符是大写字母就计数加一,然后遇到空格计数清零同时和max比较,若比max大的话那就让max变成目前的计数。代码: #include <stdio.h> #include <iostream> #include <string> using namespace std; int main() { int n,i,max = 0,s = 0; cin >> n; char a[n + 1]; getchar(); for(i = 0 ; i < n; i++) { a[i] = getchar(); if(a[i] != ' ') { if(a[i] >= 65 && a[i] <= 90) { s++; } } else { if(s > max) max = s; s = 0; } } if(s > max) max = s; cout << max <<endl; return 0; }

    B - Crossword solving

    题意: 给定两个字符串,对于较短的字符串作尽可能小的字符更换,使得更换后的字符串是较长字符串的子链。要求输出那个替换的字母个数以及具体位置(是较短字符串的第几个)

    思路 是暴力!这道题使用了暴力! 由于发现数据均是在1000以内之后,发现可以使用暴力来解决问题。 首先从两个字符串的头开始比较字符不同的个数,并且要随时记录位置,循环完一次短的字符串之后,又从较长的字符串第二个字符开始一个个与较短字符比较,依次重复,一共需要比较L - l + 1次(L为长字符串的长度,l为短字符串的长度)。最后同样在每次比较完后比较是否为最小,是的话将要进行记录和改变min值。

    然后还是超时了,我就优化了一下比较min是否已经为0,是的话可以直接结束大循环,然后还有小循环中判断计数是否已经超过了min,是的化就直接进入下一次循环。

    代码:

    #include <stdio.h> #include <iostream> #include <string> using namespace std; int main() { int n,m,min2,min1 = 1000,i,j; cin >> n >> m; char a[n],b[m]; cin >> a >> b; int c[m-n+1][n]; for(i = 0;i <= m - n;i++) { int s = 0; int x = 0; for(j = 0; j < n;j++) { if(a[j] != b[j + i]) { c[i][s] = j + 1; s++; if(s > min1) { x = 1; break; } } } if( x == 1) continue; min1 = s; min2 = i; if(s == 0) break; } cout << min1 << endl; for(i = 0;i < min1;i++) cout << c[min2][i] << ' '; return 0; }

    C - Wrath

    题意: 有一排人,每人手里拿着一把长度为 i 米的爪子 ( 为什么是爪子 )同时去捅前面排的人,有几米就能捅几个人,求最后还剩几个人。(好黑暗的题)思路: 我想从后往前计算会比较方便,从后往前一个个计算出结果,复杂度不会太高,首先比较目前这个人的爪子和他后面那个人的爪子长度 L - 1 的大小,如果大的话不变,如果小的话,说明他后面那个人相较于他捅得更远,我就直接把他后面那个人的爪子长度减一看着他自己的爪子长度,然后看此时他爪子长度是否为0,是的话,说明前面的人活下来了,存活人数加一。最后输出。代码: #include <stdio.h> #include <iostream> #include <string> using namespace std; int main() { int n,s = 1,i; cin >> n; int a[n]; for(i = 0;i < n;i++) { cin >> a[i]; } if(a[n - 1] == 0 && n != 1) s = 2; for(i = n - 2;i > 0;i--) { if(a[i] > a[i + 1] - 1) { if(a[i] == 0) s++; } else { a[i] = a[i + 1] - 1; if(a[i] == 0) s++; } } cout << s << endl; return 0; }

    D - Coloring a Tree

    题意: 有一个只有一根但是有分叉的树,先从根开,每一个节点开始向上涂颜色,然后输入每一个节点(包括顶点)的颜色,问最少需要涂多少次。

    思路: 正好在上一周听了学长讲的查并集(虽然还是不太懂 ),所以很快有了些思路,发现最后只需要比较一个节点与他的父节点的颜色是否相同,不是的话涂颜色的次数加一就行了。

    代码:

    #include <stdio.h> #include <iostream> #include <string> using namespace std; int main() { int n,t = 1,i; cin >> n; int a[n + 1],b[n + 1]; a[1] = 1; for(i = 2;i <= n; i++) cin >> a[i]; for(i = 1;i <= n; i++) { cin >> b[i]; } int c[n] = {0}; for(i = 2;i <= n; i++) { if(b[a[i]] != b[i]) t++; } cout << t << endl; return 0; }

    E - Bear and String Distance

    题意: 首先定义出字母与字母之间的差就是他们的ACII码之差的绝对值,然后单词与单词之差就是每个位置对应的字母的差之和。给出单词以及其长度,还有一个数字为它与另一个单词的差,要求求出那个单词是否存在,存在还需要任意打出其中一种即可。思路: 这道题我也不知道是啥知识点,但好一类题都是这个方法去做。 首先把所给的单词的最大差找出来,即是寻找出每个字母的最大差(与a或是与z的差,看哪个大)之和,然后比较所给的数是否大于最大差,是的话直接结束程序告诉不可能。不是的话我们就开始输出要求的单词了,因为只需要求出一种,于是我发现最简单的方法就是把所给的单词从第一个字母变为与之最大差的字母,然后每次用所给的差减去这个最大差,接着往下来,直到最后的所给的差小于某一个字母的最大差,就输出这个字母差为最后所给差的字母,接下来的字母均原封不动输出。代码: #include <stdio.h> #include <iostream> #include <string> #include <algorithm> using namespace std; int main() { int n,k,s = 0,i; cin >> n >> k; char a[n]; int d[n]; scanf("%s",a); for(i = 0;i < n;i++) { d[i] = (122 - a[i]) > (a[i] -97)?(122 - a[i]) : (a[i] -97); s = s + d[i]; } if(k > s) { cout << -1; return 0; } for(i = 0;i < n;i++) { if(k == 0) { printf("%c",a[i]); continue; } if(k - d[i] >= 0 && k != 0) { if(a[i] + d[i] == 122) printf("z"); else printf("a"); k = k - d[i]; } else if(k - d[i] < 0 && k != 0) { if(a[i] + d[i] > 122) { char c = a[i] - k; printf("%c",c); k = 0; } else { char c = a[i] + k; printf("%c",c); k = 0; } } } return 0; }

    F题还没看…之后补上。

    最新回复(0)