PAT-乙:1027 打印沙漏 (20 分)


一、题目

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

∗ ∗ ∗ ∗ ∗ *****
   ∗ ∗ ∗ ***
      ∗ *
   ∗ ∗ ∗ ***
∗ ∗ ∗ ∗ ∗ *****

输入格式:

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

输出格式:

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

输入样例:
19 *
输出样例:

∗ ∗ ∗ ∗ ∗ *****
  ∗ ∗ ∗ ***
   ∗ *
  ∗ ∗ ∗ ***
∗ ∗ ∗ ∗ ∗ *****
2


二、思路和注意事项

打印沙漏是关于等差数列的题。该等差数列是一个首项 a 1 = 1 a_1=1 a1=1,公差为 d = 2 d=2 d=2,的等差数列。第 n n n项为: a n = 1 + ( n − 1 ) × 2 = 2 n − 1 a_n=1+(n-1)\times2=2n-1 an=1+(n1)×2=2n1.
先考虑上半部分:

  1. 沙漏的第1行是是等差数列的第n项,相邻的两行之间相差d,最后一行为 1 1 1
  2. 要计算刚好构成沙漏的个数,我们只需要对等差数列求和,再减去1,因为上半部分和下半部分重复首项1.
  3. 由于上半部分总个数为 ( 1 + 2 n − 1 ) × n 2 , 所 以 总 数 S = ( 1 + 2 n − 1 ) × n 2 × 2 − 1 = n 2 − 1 \frac {(1+2n-1)\times n} 2, 所以总数S=\frac {(1+2n-1)\times n} 2\times2-1=n^{2}-1 2(1+2n1)×nS=2(1+2n1)×n×21=n21
    所以我们求上半部分的行数 n n n则为 n + 1 2 \sqrt{\frac{n+1}2} 2n+1
    如果n刚好能构成一个沙漏,则 n + 1 2 \frac {n+1}2 2n+1是一个完全平方数。
    所以该函数的意思是,传入的 N自减,当N刚好能够构成一个沙漏时,返回构成该沙漏的行数。
    下半部分:
    我们把上半部分的最后一行当做下半部分的第二行,所以我们的循环输出从i=2开始,空格的输出是上半部分的相反循环
    :

先计算上半部分一共有多少行。例如输入19时,返回值为3

int getrow(int i)
{
    
    
	int row=1;
	int cmp=sqrt((i+1)/2);
	
	while(i--) 
	{
    
    
		 if(row==cmp)  
			 {
    
    
			 	row=cmp;
				break;   					//没有break 会让i减到零 
			 }else  row++;
	}
	return row;
}



三、AC代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int getrow(int i);
int main()
{
    
     
 int N; 
cin>>N;
char a;
cin>>a;
int row=getrow(N);
int cmp=2*row*row-1;
 
 //上半部分 
	for(int i=row;i>=1;i--) 	 //控制行输出,沙漏上半部分上大下小,故从第n项输出到第1项.
	{
    
    
		for(int k=0;k<row-i;k++)  //第一行空格为0,第一行空格为1,..第n行空格为n-1
		{
    
    		
		printf(" ");
		}
								   //输出空格完以后输出字符
		for(int j=2*i-1;j>=1;j--)  //控制列,第n项个数为2*n-1 
		{
    
    
		if(j==1) printf("%c\n",a);
		else printf("%c",a);
		} 
	}
	
	//下半部分
	for(int i=2;i<=row;i++)  //把沙漏上半部分最后一行当做下半部分的第一行,所以从2开始循环
	{
    
    
	    for(int k=row-i;k>=1;k--)
		{
    
      
		  printf(" ");
		} 
		for(int j=1;j<=2*i-1;j++)
		{
    
    
			if(j<2*i-1) printf("%c",a);
			else printf("%c\n",a);
		}
	} 
	printf("%d\n",N-cmp);  //输出给定的数字N和刚好构成沙漏的数量之差
}
	
	
int getrow(int i)
{
    
    
	int row=1;
	int cmp=sqrt((i+1)/2);
	
	while(i--) 
	{
    
    
		 if(row==cmp)  
			 {
    
    
			 	row=cmp;
				break;   					//没有Break 会让temp减到零 
			 }else  row++;
	}
	return row;
}
 

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/SKMIT/article/details/113861736