PTA 1027 打印沙漏 (20 分)

本文介绍了一个程序设计挑战,使用给定的符号打印出沙漏形状,并尽量消耗最多符号。通过控制循环,实现沙漏形状的上下对称打印,最后输出剩余未使用的符号数量。

1027 打印沙漏 (20 分)

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

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

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

输入格式:

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

输出格式:

首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
代码思路:主要是要注意循环的控制;

#include<stdio.h>
#include<string.h>
int main()
{
	int n;
	char c;
	scanf("%d",&n);
	getchar();
	scanf("%c",&c);
	int i,j;
	int sum=1;
	int t=1;
	for(i=3;(sum+i*2)<=n;i=i+2)
	{
		sum=sum+i*2;
		t=i;
	}
	int t1=t,t2=1;
 for(i=0;t1>0;i++,t1=t1-2)//输出上半部分
   {
   	int flag=0;
   	int x=t1;
   	for(j=0;x>0;j++)
   	{
   		if(i==j)
   		{
   			flag=1;
		}
		   if(flag==0)
		   {
		   	printf(" ");
		   }
		   else 
		   {
		   printf("%c",c);
		   x--;
	        }
   		
	   }
	   printf("\n");
	}	
	int x=t2;
 for(i=i-2;i>=0;i--) //输出下半部分
 {
 	int flag=0;
 	x=t2+2;
 	t2=t2+2;
 	for(j=0;x>0;j++)
 	{
 		if(i==j)
 		{
 		flag=1;	
		 }
		 if(flag==0)
		   {
		   	printf(" ");
		   }
		   else 
		   {
		   printf("%c",c);
		   x--;
	        }
	 }
	 printf("\n");
 }
	
	printf("%d",n-sum);
	return 0;
}
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]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一蓑烟雨荏平生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值