当前位置:   article > 正文

PTA L1-002 打印沙漏(详解)_pta打印沙漏

pta打印沙漏

前言:本期是关于pta题目打印沙漏的具体解法,今天你c了吗?

 题目:

本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印

  1. *****
  2. ***
  3. *
  4. ***
  5. *****

所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。

给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。

输入格式:

输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。

输出格式:

首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。

输入样例:

  1. 19 *

输出样例:

  1. *****
  2. ***
  3. *
  4. ***
  5. *****
  6. 2

代码实现: 

  1. #include<stdio.h>
  2. #include<math.h>
  3. int main()
  4. {
  5. int n = 0;
  6. char c = 0;
  7. scanf("%d %c", &n, &c);
  8. int i = 0;
  9. int row = 0;
  10. for (i = 0; i <sqrt(n); i++)
  11. {
  12. if (2 * (i * i + 2 * i) + 1 > n)
  13. {
  14. row = i - 1;
  15. break;
  16. }
  17. }
  18. //打印上半部分
  19. for (i = row; i > 0; i--)
  20. {
  21. //打印空格
  22. int j = 0;
  23. for (j = row - i; j > 0; j--)
  24. {
  25. printf(" ");
  26. }
  27. //打印内容
  28. for (j = 0; j < 2 * i + 1; j++)
  29. {
  30. printf("%c", c);
  31. }
  32. printf("\n");
  33. }
  34. //打印中间
  35. for (i = 0; i < row; i++)
  36. {
  37. printf(" ");
  38. }
  39. printf("%c", c);
  40. printf("\n");
  41. //打印下半部分
  42. for (i = 1; i <= row; i++)
  43. {
  44. //打印空格
  45. int j = 0;
  46. for (j = 0; j < row - i; j++)
  47. {
  48. printf(" ");
  49. }
  50. //打印内容
  51. for (j = 0; j < 2 * i + 1; j++)
  52. {
  53. printf("%c", c);
  54. }
  55. printf("\n");
  56. }
  57. printf("%d", n - (2 * (row * row + 2 * row) + 1));
  58. return 0;
  59. }

大致思路: 

1. 求出沙漏一半图形的行数

2. 打印上半部分 +单独打印中心那一颗+打印下半部分

3. 打印未能用上的剩余符号数

代码解读:

part 1

  1. int i = 0;
  2. int row = 0;
  3. for (i = 0; i <sqrt(n); i++)
  4. {
  5. if (2 * (i * i + 2 * i) + 1 > n)
  6. {
  7. row = i - 1;
  8. break;
  9. }
  10. }

1. for循环求出一半图像的行数的所有可能取值, 一半图像的行数是小于sqrt(n)的

   eg.  输入17   沙漏图形一半的行数是2,小于sqrt(17)

    sqrt是开平方函数

2. 求出上半图形+下半图形的和的通项式:2(i^2+2*i)

     再加上最中心的那一颗:2(i^2+2*i)+1  

     此时2(i^2+2*i)+1就代表了整个沙漏组成符号的个数n

     可以发现:通项式中的i可以看成一半图形的行数

                       若是for循环中有一个i刚好能使得2(i^2+2*i)+1  ==n,则i就是一半图形的行数

                       若是for循环中找不到能刚好使得2(i^2+2*i)+1  ==n的行数i,那就只能找到能使得                          沙 漏成形的最大化行数i,怎么才是最大化的行数i呢?方法如下:

  1. if (2 * (i * i + 2 * i) + 1 > n)
  2. {
  3. row = i - 1;
  4. break;
  5. }

找到最适配行数(恰好使得 2(i^2+2*i)+1  ==n的行数)后面紧跟着的一个行数

判断条件是:2 * (i * i + 2 * i) + 1 > n     此方法同样也能找到最适配的行数

那么正确的行数是:i-1

找到正确行数后break跳出for循环

part 2

  1. //打印上半部分
  2. for (i = row; i > 0; i--)
  3. {
  4. //打印空格
  5. int j = 0;
  6. for (j = row - i; j > 0; j--)
  7. {
  8. printf(" ");
  9. }
  10. //打印内容
  11. for (j = 0; j < 2 * i + 1; j++)
  12. {
  13. printf("%c", c);
  14. }
  15. printf("\n");
  16. }

   打印上半部分:

1. 打印的行数总共是row行

    一行的打印:   

   a. 先打印空格:规律是0,1,2……

   b. 再打印符号:规律:求出上半部分图形的通项:2*i+1

   c. 打印完一行后要换行

part 3    

  1. //打印中间
  2. for (i = 0; i < row; i++)
  3. {
  4. printf(" ");
  5. }
  6. printf("%c", c);
  7. printf("\n");

  打印中间唯一的一个符号:

1. 打印空格:

    规律:空格的个数是行数的个数

2. 打印内容:只打印一个

3. 打印完要换行

part 4             

  1. //打印下半部分
  2. for (i = 1; i <= row; i++)
  3. {
  4. //打印空格
  5. int j = 0;
  6. for (j = 0; j < row - i; j++)
  7. {
  8. printf(" ");
  9. }
  10. //打印内容
  11. for (j = 0; j < 2 * i + 1; j++)
  12. {
  13. printf("%c", c);
  14. }
  15. printf("\n");
  16. }

  打印下半部分: 

  1. 打印的行数总共是row行

     一行的打印:   

   a. 先打印空格:规律是……2,1,0

   b. 再打印符号:规律:求出下半部分图形的通项:2*i+1

   c. 打印完一行后要换行

part 5 

printf("%d", n - (2 * (row * row + 2 * row) + 1));

 打印未用的符号数

本期完!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/935726
推荐阅读
相关标签
  

闽ICP备14008679号