PTAL1-054 福到了(15 分)算法详解与坑点分析

博客围绕编写程序将汉字倒着输出展开。介绍了输入输出格式,涉及倒置输出和判定是否倒置两个主要算法。还指出从算法到实现需注意IO格式,如处理空格和换行符,不同语言处理方式有别,最后表示掌握算法和坑点处理手段一般能通过。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

“福”字倒着贴,寓意“福到”。不论到底算不算民俗,本题且请你编写程序,把各种汉字倒过来输出。这里要处理的每个汉字是由一个 N x N 的网格组成的,网格中的元素或者为字符“@”或者为空格。而倒过来的汉字所用的字符由裁判指定。
输入格式:
输入在第一行中给出倒过来的汉字所用的字符、以及网格的规模 N (不超过100的正整数),其间以 1 个空格分隔;随后 N 行,每行给出 N 个字符,或者为“@”或者为空格。
输出格式:
输出倒置的网格,如样例所示。但是,如果这个字正过来倒过去是一样的,就先输出“bu yong dao le”,然后再用输入指定的字符将其输出。
输入样例 1:
$ 9
@ @@@@@
@@@ @@@
@ @ @
@@@ @@@
@@@ @@@@@
@@@ @ @ @
@@@ @@@@@
@ @ @ @
@ @@@@@
输出样例 1:
$ $
$ $ $ $
$
$$ KaTeX parse error: Can't use function '$' in math mode at position 2: $̲ $ $ $ $ KaTeX parse error: Can't use function '$' in math mode at position 2: $̲ $ $ $ $
输入样例 2:
& 3
@@@
@
@@@
输出样例 2:
bu yong dao le
&&&
&

&&&

本题链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805076512587776

通过本题,本人知道了算法与最终实现的差距有时还是挺大的,先讲算法,本题涉及的主要算法不难,一共两个:

1.倒置输出

通过仔细观察规律,不难发现其实就是对原来正序输出的二重循环的循环变量稍作修改,只要将循环变量的初始值改为N-1,变量的下界改为0即可,即从图形的右下角,从右往左,输出完一行,再输出上一行,直到第一行输出完毕。

2.判定是否需要倒置

如果你倒置输出的算法原理搞懂了,你会知道哪两个字符是需要比较的,比如最简单的情况,第一行第一个字符和右下角的字符,即最后一行从右往左数第1个字符是需要比较的,不妨将两个字符的表示写为A[0][0]和A[N-1][N-1],接着第一行第二个字符和最后一行从右往左数第二个字符是需要比较的,即A[0][1]和A[N-1][N-2]是需要比较的,这里的行数没有变,变的是列数。刚开始的0对应N-1,接着是1对应N-2,不难得出,如果列数为j,则对应的列数为N-1-j。需要注意的是需要换行比较的时候,行数就需要变化,即原字符所在行数增加,待比较字符所在行数减少,其中的规律也不难得出,如果行数为i,则对应的行数为N-i-1。至此,我们还需要一个判定是否需要倒置的标识变量,不妨设为flag,假设它的初值是1,表示不用倒,则你可以写在外循环的判定条件中,如果不用倒,则继续比较字符。一旦两个字符不相等,则置flag=0,跳出内循环,外循环判定flag不为1,结束整个循环。

有了核心算法还不够,你还需要实现,而从算法设计完成到实现要经过一些过程,其影响结果的主要过程就是IO格式,而此题的坑点就是:输入存在空格和换行符的情况,以下是坑点的具体分析:

如果你用C++的IO方式,在键入字符时,如果使用了getline函数,那么你可以不去关心有换行符的情况。如果你用C的IO方式,那么你就必须在每次需要换行时处理换行的情况,即你需要在每次需要换行时使用getchar来接收换行符。

但无论是C还是C++,抑或别的语言,应该都需要处理在开头键入数字后的换行符,这个换行符会影响接下来字符的输入,C或C++可以用getchar来接收换行符。如果你用C的IO方式,你可能在接收字符的时候不去一个个地接收字符,而是用gets函数一次接收一行字符,但在PTA这个平台上是不允许的,这是一个PTA隐藏的公共坑点,至于原因,我之前有问过相关负责人,gets是不安全的函数,已经禁用了。那么,C语言使用者总共需要3个getchar,一个是来接收一开始输入数字后的换行符,一个是用来接收每次键入的字符,还有一个是接收每次需要换行时输入的换行符。C++如果使用getline那么只需要一个getchar。

有了核心算法与坑点的处理手段,如果没有特殊情况的话,你已经能AC了,以下是具体代码:

#include<iostream>
using namespace std;
int main()
{
	int N;
	char c;
	cin>>c>>N;
	getchar();//注意!接收换行符,以免留在缓冲区被下一次getchar读取 
	char fu[100][100];
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			fu[i][j]=getchar();//使用getchar读入任意字符 
			if(fu[i][j]!=' ')//如果不为空格,修改字符 
			fu[i][j]=c;
		}
		getchar();//注意!接收换行符,以免留在缓冲区被下一次getchar读取 
	}
	int flag=1;//定义标识,初始化为1,代表不用倒
	for(int i=0;i<N&&flag;i++)//如果不用倒,则继续 
	for(int j=0;j<N;j++)
	if(fu[i][j]!=fu[N-i-1][N-1-j])//如果当前字符不等于对应字符 
	{
		flag=0;//说明需要倒 
		break;
	}
	if(flag)
	cout<<"bu yong dao le\n";
	for(int i=N-1;i>=0;i--)
	{
		for(int j=N-1;j>=0;j--)//i,j的初始值和结束条件都改变,递减,输出 
		cout<<fu[i][j];
		cout<<'\n';
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值