1. 程式人生 > >PAT(乙級)1027 列印沙漏

PAT(乙級)1027 列印沙漏

題目描述:

本題要求你寫個程式把給定的符號列印成沙漏的形狀。例如給定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; }