PTA L1系列题解(C语言)(L1_049 -- L1_056)

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值