PAT(乙級)1027 列印沙漏
阿新 • • 發佈:2019-01-14
題目描述:
本題要求你寫個程式把給定的符號列印成沙漏的形狀。例如給定17個“*”,要求按下列格式列印
所謂“沙漏形狀”,是指每行輸出奇數個符號;各行符號中心對齊;相鄰兩行符號數差2;符號數先從大到小順序遞減到1,再從小到大順序遞增;首尾符號數相等。給定任意N個符號,不一定能正好組成一個沙漏。要求打印出的沙漏能用掉儘可能多的符號。
輸入格式:
輸入在一行給出1個正整數N(<=1000)和一個符號,中間以空格分隔。輸出格式:
首先打印出由給定符號組成的最大的沙漏形狀,最後在一行中輸出剩下沒用掉的符號數。
解題方法:
利用遞迴的思想求出沙漏上半部分的行數,此題每一行都是奇數,需要的符號總數是(1+3*2+5*2+……),所以利用遞迴當第w次時和大於輸入的n,則跳出迴圈。之後利用for迴圈計算當上半部份為w行時需要的符號數,如果大於n,則w=w-1。之後根據w的值列印沙漏。最後計算未使用的符號數。
易錯點:
舉個例子,上半部分為3行的沙漏,即最上層為5個符號的沙漏需要17個符號,當我們輸入一個數,比如14,此時第一個for迴圈執行3次(因為第2次的時候sum小於14),即w等於3,但是如果w=3畫沙漏需要17個符號,所以需要第二個for迴圈來判斷我們這個w的值到底是w還是w-1。
程式:
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
int n;
string c;
cin>>n>>c;
int sum=0;
int w;
int j;
//求沙漏上半部分行數
for( w=1;w<1000;w++)
{
if((1+sum)<n){
sum+=((2*w+1)*2);
}else
{
break;
}
}
int sum1=0;
for (int i = 1; i < w; ++i)
{
sum1+=(2*i+1)*2;
}
if (n>=(1+sum1))
{
w=w;
}else{
w=w-1;
}
//繪製沙漏
//上半部分
for (int i = 0; i < w; ++i)
{
for (j = 0; j < i; ++j)
{
cout<<" ";
}
for (int m = 0; m < 2*(w-j)-1; ++m)
{
cout<<c;
}
cout<<endl;
}
//下半部分
for (int i =w-1; i >0; --i)
{
for (j = 1; j <i; ++j)
{
cout<<" ";
}
for (int m = 0; m<2*(w-j+1)-1; ++m)
{
cout<<c;
}
cout<<endl;
}
//計算未用符號個數
int sum2=0;
for (int i = 1; i < w; ++i)
{
sum2+=(2*i+1)*2;
}
cout<<n-(1+sum2);
return 0;
}