星号棱形,数字棱形及其他对称图形的分析方法

论坛 期权论坛 脚本     
已经匿名di用户   2022-7-2 21:58   1763   0

星号棱形,数字棱形及其他对称图形的分析方法


这一类图形其实都可以运用其对称性进行分析,选定中心图案或数字,进行规律分析来实现的。
1. 先来一道简单的题。

输入一个整数n,输出n行n列的“ * ”号,代码如下

//比较简单,直接上两个for循环就行了。
#include <stdio.h>
int main()
{
 int i,n,k;
 scanf("%d",&n);
 for(i=0;i<n;i++)
 {
  for(k=0;k<n;k++)
  {
   printf("*");
  }
  printf("\n");
 }
 return 0;
}

2.输出入下图所示的棱形。

  *
 ***
*****
 ***
  *

我们只需要输出以上棱形就行了,通过观察,棱形一共有5行,我们可以用5个printf()函数进行输出。但是,用这种方式难免太机械化了,如果要输出100行,很明显这种方法行不通,还有没有其他方法呢?

3.

Description
由键盘输入正数n(n<30),要求输出如下2*n+1行的菱形图案。

输出格式
菱形右边不留多余空格

输入样例
2
输出样例
  *
 ***
*****
 ***
  *
(题源 SCAU )

这道题用printf()函数输出根本不可能了,很容易地,我们想到了应该用循环来解决问题。

先把这个棱形分成上下两部分,设置一个外层循环控制行,再使用内层循环打印空格及*号。

*
***
*****

***
*

(红色为上半部分,绿色为下半部分,通过每部分的规律来实现。因为分上下部分,所以就需要两个for循环)

#include <stdio.h>
int main()
{
 int n,i,k,j;
 scanf("%d",&n);
 for(i=1,k=1;i<=n+1;i++)
 {
  for(j=1;j<=n-i+1;j++)
  {
   printf(" ");   //打印空格
     }
  for(j=1;j<=k;j++)
  {
   printf("*");   //打印*号
  }
  printf("\n");
  k+=2;
 }
 for(i=1,k=2*n-1;i<=n;i++)
 {
  for(j=1;j<=i;j++)
  {
   printf(" ");    //打印空格
  }
  for(j=1;j<=k;j++)
  {
   printf("*");    //打印*号
  }
  printf("\n");
  k-=2;
 }
 return 0;
}

我们发现,凡是这些图形,都可以把他们分成若干分,一个个地来实现。

还有没有更好的办法呢?

不难发现,棱形是一个上下呈对称的图形,还可以利用对称性来更好的解决问题。

题目要求输出的行数是2*n+1行,是奇数,因此,还可以用相反数来控制行数。


#include "stdio.h"
int main()
{   int n,i,j;
   scanf("%d",&n);
   for(i=-n;i<=n;i++)    //一共要打印2*n+1行,从-n到n。
   {
        for(j=1;j<=abs(i);j++)  printf(" ");
        for(j=1;j<=2*n+1-2*abs(i);j++)  printf("*");
        printf("\n");
   }
    return 0;
}

代码量是不是瞬间就减少了好多。

下面我们来一步步进行分析!

1.) 首先,棱形是一个上下左右对称的图形,肯定存在某种数学规律。

2.) 其次,设置绝对值就是利用了对称性。

3.)以当n=2为例。(以---代替空格)

--* 空格数:2 *号数:1
-*** 空格数:1 *号数:3
***** 空格数:0 *号数:5 ---------->
以上下对称轴处为中心行,在打印*号时用相应行数的绝对值的四则运算来
-*** 空格数:1 *号数:3 进行计算要打印多少*号
--* 空格数:2 *号数:1

好了,我们通过选定了中心行很容易地打印了*号棱形。

既然我们利用了上下对称的规律,有没有可以利用左右对称呢?

4.

  打印星号空心菱形
 描述
由键盘输入n(n为奇数),打印如下图空心菱形

例n=7
   *
  * *
 *   *
*     *
 *   *
  * *
   *
输入格式

奇正整数

输入样例
3
输出样例
 *
* *
 *

当然,这道题也可以把它分成若干分,一个个来实现。(代码如下)

#include <stdio.h>
int main(void)
{
 int i,j,n;
 scanf("%d",&n);
 for(i=1;i<=(n+1)/2;i++)
 {
  for(j=1;j<=(n+1-2*i)/2;j++)
  {
   printf(" ");
  }
  printf("*");
  if(i==1)
  {
   printf("\n");
  }
  else 
  {
   for(j=1;j<=2*i-3;j++)
   {
    printf(" ");
   }
   printf("*\n");
  }
 }
 for(i=1;i<=(n-1)/2;i++)
 {
  for(j=1;j<=i;j++)
  {
   printf(" ");
  }
  printf("*");
  for(j=1;j<=n-2*i-2;j++)
  {
   printf(" ");
  }
  if(i<=(n-3)/2)
  {
   printf("*\n");
  }
  
 }
 return 0; 
}

超级长,而且里面的数学表达式要算很久。

若采用对称的方法:(代码如下)

#include <stdio.h>
int main(void)
{
 int i,j,n;
 scanf("%d",&n);
 n=(n-1)/2;
 for(i=-n;i<=n;i++)
 {
  for(j=1;j<=2*n+1-abs(i);j++)
  {
   if(j==abs(i)+1||j==2*n+1-abs(i))   printf("*");
   else printf(" ");
  }
  printf("\n");
 }
 return 0; 
}

采用了上下左右对称的方法,并且运用数学公式,符合规律的打印输出相应的空格或*号。

以n=7为例分析:

   *
  * *
 *   *
*     *
 *   *
  * *
   *

在代码中,第二个for循环用来控制一行需要输出的字符数,这里的字符是空格和*号。

还是选定上下对称轴的那行作中心行。

一行处除特殊外都要输出两个*号,排除特殊性来分析。

然后在if语句中,很容易发现第一个判断“j==abs(i)+1”的规律,

第二个判断语句是以中心行最右边的*号为基点缩回的。

(.......未完)

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:81
帖子:4969
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP