PTA练习题1027 打印沙漏 (20分)

该篇博客介绍如何使用C语言编写程序打印沙漏形状,重点在于确定行数及符号排列规则。博主分享了其解决思路,通过计算行数并以递减再递增的方式输出符号,最终给出了输入输出样例并提及剩余未使用的符号数量。

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





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

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

输入格式:
输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。
输出格式:
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。

输入样例:
19 *

输出样例:





2
思路;想了一天终于弄出来了,觉得难点在于计算需要打印的行数,计算一半就好了,先打上半部分,第一行打印的数量就是行数的数量,然后逐行减2,减到1,反转,递增。

#include<stdio.h>
#include<math.h>
int main(){
   
   
	char s='*';
	int n=5;
	int sums=3
PTA乙级1027打印沙漏问题要求将给定符号打印沙漏形状,且使用尽可能多的符号,最后输出剩余未使用的符号数。以下是几种不同的C++解决方案: ### 方案一 ```cpp #include<stdio.h> #include<iostream> #include<math.h> using namespace std; int main() { int n; char ch; cin>>n>>ch; int num=sqrt((n+1)/2); for(int i=0;i<num;i++) { for(int k=0;k<i;k++) { cout<<" "; } for(int j=(num-i)*2-1;j>0;j--) { cout<<ch; } cout<<endl; } for(int i=0;i<num-1;i++) { for(int k=num-(i+2);k>0;k--) { cout<<" "; } for(int j=0;j<2*(i+2)-1;j++) { cout<<ch; } cout<<endl; } cout<<n-(num*num*2-1); } ``` 此方案通过计算沙漏的层数`num`,先输出上半部沙漏,再输出下半部沙漏,最后输出剩余符号数。其中`num`是通过`sqrt((n + 1) / 2)`计算得到的,代表上方三角形的层数,一个沙漏大小是`num`的平方乘以2再减1 [^1]。 ### 方案二 ```cpp #include <iostream> #include <iomanip> using namespace std; int main() { int n; char ch; cin >> n >> ch; int max = 1; if (n == max) { cout << ch << "\n" << 0; return 0; } n -= max; while (max<n) { if (n<2 * (max+2)) break; else max +=2; n -= 2 * max; } for (int i = max; i>0; i = i-2) { for (int j = 0; j < (max - i) / 2; j++) cout << " "; for (int j = 0; j < i; j++) cout << ch; cout << '\n'; } for (int i = 3; i <= max; i = i + 2) { for (int j = 0; j < (max - i) / 2; j++) cout << " "; for (int j = 0; j < i; j++) cout << ch; cout << '\n'; } cout << n; } ``` 该方案先处理输入为1的特殊情况,然后通过循环找到最大一层的符号数`max`,接着别输出沙漏的上半部和下半部,最后输出剩余符号数 [^2]。 ### 方案三 ```cpp #include<iostream> using namespace std; int main() { int n,i=3; char c; cin>>n>>c; n=n-1; while((n-i*2)>=0) { n=n-i*2; i+=2; } i = i - 2; int temp = i; for(;i>1;i-=2) { for(int x=(temp-i)/2;x>0;x--) { cout<<" "; } for(int y=i;y>0;y--) { cout<<c; } cout<<endl; } for(;i<=temp;i+=2) { for(int x=(temp-i)/2;x>0;x--) { cout<<" "; } for(int y=i;y>0;y--) { cout<<c; } cout<<endl; } cout<<n<<endl; return 0; } ``` 此方案先通过`while`循环计算剩余符号数,然后记录首行符号数`i`,别输出沙漏的上半部和下半部,最后输出剩余符号数 [^3]。 ### 方案四 ```cpp #include<iostream> #include<cmath> using namespace std; int main() { int n; char a; cin>>n>>a; int x=sqrt((n+1)/2); int yushu=n+1-x*x*2; int count=0; for(int i=2*x-1;i>=1;i=i-2) { for(int j=0;j<count;j++) { printf(" "); } for(int j=0;j<i;j++) { cout<<a; } printf("\n"); count++; } for(int i=3;i<=2*x-1;i=i+2) { for(int j=0;j<count-1-1;j++) { printf(" "); } for(int j=0;j<i;j++) { cout<<a; } printf("\n"); count--; } printf("%d",yushu); return 0; } ``` 该方案计算出上半部打印行数`x`和剩余字符数`yushu`,然后别输出沙漏的上半部和下半部,最后输出剩余字符数 [^4]。 ### 方案五 ```cpp #include<bits/stdc++.h> using namespace std; int main() { int N; char c; cin>>N>>c; int mid=(int)sqrt((N+1)/2*1.0); int row=2*mid-1; int space=0; for(int i=row;i>=1;i-=2) { for(int j=0;j<space;j++) { printf(" "); } space++; for(int j=0;j<i;j++) { printf("%c",c); } printf("\n"); } space--; for(int i=3;i<=row;i+=2) { space--; for(int j=0;j<space;j++) { printf(" "); } for(int j=0;j<i;j++) { printf("%c",c); } printf("\n"); } printf("%d",N-2*mid*mid+1); return 0; } ``` 此方案先获取漏斗上半部的行数`mid`和总行数`row`,然后别输出沙漏的上半部和下半部,最后输出剩余字符数 [^5]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值