L1-049 天梯赛座位分配
题目内容:
解题思路:
错解:
看到这题,我最开始的想法是找出每次排队时所参与的队伍数,然后每次增加这个数循环直接输出,但是当只有一个队伍时,需要隔一个位置坐,这种情况我在上面记录队伍数时遇到一个队伍的情况增加了1。但是后面又遇到当先开始的队伍先排完时,后面的队伍应该增加的数值是需要改变的。以上问题等等,我意识到这种方式并不是最优解。
在这个时候,我大概想到了几个需要注意的点:
1.一开始就只有一个队伍,也就是直接需要隔两个位置坐。
2.前面的队伍先排完了,或者后面的队伍先排完了,这些情况要不同的处理。
3.当只有一个队伍前排的不在这一队中,即最后一个队伍的第一个人和前面的人差1,而这个队伍里后面的人都要隔两个位置。
正解:
我采取了填数组的方式,定义一个三维数组,然后遍历,当该所学校不足这么多队伍时跳过。处理同学校人不能连着,我用一个标记量past记录上一个人是那所学校对,判断past和现在需要去处理的学校相同,相同则 +1 , 由于前面的值本身是和正确值差 1 ,然后输出时 +1 就能够刚好相同,然后每次增加2, 同样也差 1 输出时 +1 能抵消。
C代码展示:
#include <stdio.h>
int main() {
int n, s[105], team[105][15][15], num = 1, max = 0, past = -1;
// 定义变量n(元素数量),s数组(存储每个元素的值),team数组(存储编号),num(当前编号),max
(元素值的最大值),past(上一个处理的元素索引)
scanf("%d", &n);
for (int i = 1; i <= n; i++) { // 循环读取每个元素的值
scanf("%d", &s[i]);
if (s[i] > max) max = s[i]; // 更新最大值
}
for (int i = 1; i <= max; i++) { // 循环初始化编号
for (int j = 1; j <= 10; j++) { // 外层循环,可能表示不同的组或条件
for (int k = 1; k <= n; k++) { // 内层循环,遍历每个元素
if (s[k] < i) continue; // 如果元素值小于当前编号的阈值,则跳过
if (past == k) { // 如果当前元素是连续处理的元素
team[k][j][i] = num + 1; // 分配编号,num加1
num += 2; // num增加2,为下一个编号做准备
} else { // 否则
team[k][j][i] = num; // 分配编号
num++; // num增加1
}
past = k; // 更新past为当前元素的索引
}
}
}
for (int k = 1; k <= n; k++) { // 循环输出编号
printf("#%d\n", k); // 输出元素索引
for (int i = 1; i <= max; i++) { // 循环输出每个元素的编号
if (s[k] < i) continue; // 如果元素值小于当前编号的阈值,则跳过
for (int j = 1; j < 10; j++) { // 循环输出编号
printf("%d ", team[k][j][i]); // 输出编号
}
printf("%d\n", team[k][10][i]); // 输出最后一个编号,并换行
}
}
return 0;
}
L1-050 倒数第N个字符串
题目内容:
解题思路:
本题主要难点在于将题目意思转换成更简单的表达。所以我从题目入手,简单说一下我的理解。
第 1 个序列 : aaa;
第 2 个序列 : aab;
第 3 个序列 : aac;
…………
第 26个序列 : aaz;
第 27个序列 : aba;
第 28个序列 : abb;
…………
第676个序列 : azz;
第677个序列 : baa;
第678个序列 : bab;
…………
按照上面的顺序,是不是有一个熟悉的东西和它很像:
进制转换
那么思路就很明晰了,它就是26进制数。
取余求商,商再取余求商,以此类推,求出该26进制数。
按照本题的题目,有两点需要注意,它是反向排序,而且数是从1开始。
根据第一点,只需要用 ' z ' - 该位的数;
第二点,只需要将输入的 n - 1,让这个数从 0 开始即可。
想明白上面这一些,题目就很简单了,也可以参考一下我的代码,也很容易看懂。
C代码展示:
#include <stdio.h>
int main() {
int l, n, s[10]; // 定义整数变量l(输出的字母序列的长度),n(要转换的正整数),以及整数数组s(用于存储转换过程中的中间结果)
scanf("%d %d", &l, &n); // 读取整数l和n
n--; // 将n减1,因为后面计算时是从0开始的
for (int i = 0; i < l; i++) { // 循环l次,每次计算n除以26的余数
s[i] = n % 26; // 计算n除以26的余数,并存储在数组s中
n = n / 26; // 更新n为n除以26的商,为下一次循环做准备
}
for (int i = 0; i < l; i++) { // 循环l次,输出转换后的字母序列
printf("%c", 'z' - s[l - i - 1]); // 计算并输出字母,'z' - s[l - i - 1]是为了将余数转换为字母('a'到'z')
}
printf("\n");
return 0;
}
L1-051 打折
题目内容:
解题思路:
略。
C代码展示:
#include <stdio.h>
int main()
{
int a, b;
scanf("%d %d", &a, &b);
printf("%.2f\n", 1.0 * a / 10 * b);
return 0;
}
L1-052 2018我们要赢
题目内容:
解题思路:
略。
C代码展示:
#include <stdio.h>
int main()
{
printf("2018\nwo3 men2 yao4 ying2 !\n");
return 0;
}
L1-053 电子汪
题目内容:
解题思路:
略。
C代码展示:
#include <stdio.h>
int main()
{
int a, b;
scanf("%d %d", &a, &b);
for (int i=0; i<a+b; i++){
printf("Wang!");
}
printf("\n");
return 0;
}
L1-054 福到了
题目内容:
解题思路:
本题主要分为三个步骤:
第一步,读入和输出。
第二步,判断颠倒前后是否一样。
第三步,字符替换。
针对第三点字符替换,我的处理方法是在读入时进行修改,采用 getchar() 单字符的读入,当读入字符不是空格时修改为指定输出字符。
对于第二步,可以用循环从前后两个方向同时进行读取,然后比较。
C代码展示:
#include <stdio.h>
int main() {
char s[105][105], x, flag = 1; // 定义一个二维字符数组s,用于存储矩阵;定义字符变量x,用于存储用户输入的字符;定义标志变量flag,用于标记矩阵是否对称
int n; // 定义整数变量n,用于存储矩阵的大小
scanf("%c %d", &x, &n); // 读取一个字符和矩阵的大小
getchar(); // 读取并丢弃缓冲区中的换行符,为后续的getchar()做准备
for (int i = 0; i < n; i++) { // 外层循环,遍历矩阵的每一行
for (int j = 0; j < n; j++) { // 内层循环,遍历矩阵的每一列
if (getchar() != ' ') s[i][j] = x; // 如果读取的字符不是空格,将矩阵的相应位置设置为x
else s[i][j] = ' '; // 否则,设置为空格
}
getchar(); // 读取并丢弃行与行之间的换行符
}
for (int i = 0; i < n; i++) { // 遍历矩阵的每个元素,检查矩阵是否对称
for (int j = 0; j < n; j++) {
if (s[i][j] != s[n-1-i][n-1-j]) flag = 0; // 如果元素与其对称元素不相等,设置标志为0
}
}
if (flag) { // 如果矩阵是对称的
printf("bu yong dao le\n");
}
for (int i = 0; i < n; i++) { // 遍历矩阵的转置
for (int j = 0; j < n; j++) {
printf("%c", s[n-1-i][n-1-j]); // 输出矩阵的转置
}
printf("\n");
}
return 0;
}
L1-055 谁是赢家
题目内容:
解题思路:
本题主要是在进行两个判断,一个是观众投票的比较,另一个是是否有三名评委投同一个人。
两个判断,建议先进行第二个,只要被三位评委同时投票,那观众投票的结果就不重要了;在没有三位评委同时投票的时候,再进行第一个判断。
C代码展示:
#include <stdio.h>
int main()
{
int pa, pb, a, b, c;
scanf("%d %d", &pa, &pb);
scanf("%d %d %d", &a, &b, &c);
if (a + b + c == 0) printf("The winner is a: %d + 3\n", pa);
else if (a + b + c == 3) printf("The winner is b: %d + 3\n", pb);
else{
if (pa > pb) printf("The winner is a: %d + %d\n", pa, 3-a-b-c);
else printf("The winner is b: %d + %d\n", pb, a+b+c);
}
return 0;
}
L1-056 猜数字
题目内容:
解题思路:
这题不是一个合格的20分题,它的思路很直接,读取数据的同时求和,求平均值,然后遍历存储的数组,判断差值,记录当前最小的差值,以及索引位。
C代码展示:
#include <stdio.h>
#include <math.h>
int main()
{
int n, num[10005]={0}, sum = 0, min = 1000000, k=0;
char name[10005][10];
scanf("%d", &n);
for (int i=0; i<n; i++){
scanf("%s %d", name[i], &num[i]);
sum += num[i];
}
int avg = sum / n / 2;
for (int i=0; i<n; i++){
if (abs(num[i] - avg) < min){
k = i;
min = abs(num[i] - avg);
}
}
printf("%d %s\n", avg, name[k]);
return 0;
}