自測-1 打印沙漏 (20分)

本題要求你寫個程序把給定的符號打印成沙漏的形狀。例如給定17個“*”,要求按下列格式打印

*****
 ***
  *
 ***
*****

所謂“沙漏形狀”,是指每行輸出奇數個符號;各行符號中心對齊;相鄰兩行符號數差2;符號數先從大到小順序遞減到1,再從小到大順序遞增;首尾符號數相等。

給定任意N個符號,不一定能正好組成一個沙漏。要求打印出的沙漏能用掉儘可能多的符號。

輸入格式:
輸入在一行給出1個正整數N(≤1000)和一個符號,中間以空格分隔。

輸出格式:
首先打印出由給定符號組成的最大的沙漏形狀,最後在一行中輸出剩下沒用掉的符號數。

輸入樣例:

19 *

輸出樣例:

*****
 ***
  *
 ***
*****
2

解題思路:在OJ上,圖形題並不是太多,所以這個題目非常好,因爲你不能用print語句直接打印,給定任意N個符號,不一定能正好組成一個沙漏。要求打印出的沙漏能用掉儘可能多的符號。題眼在這裏,輸出多少個符號,隨意,輸出什麼符號,隨意,有兩個隨意在這裏,我們就要去找行列的數值運算關係,也就是二維中的數量關係,這是一個非常重要的考查點,因爲涉及圖形學的問題都是從這裏起步的,這個題目的難點在哪呢?就是這個沙漏形狀,因爲我們的作業裏一向都是三角形,最多出現菱形,老師都覺得,哎呀,太難了吧,學生不一定會,其實如果你真正掌握了三角形的各個形態怎麼處理,菱形就是double一下,只不過double的時候要處理空格問題,這個沙漏和菱形類似,但是它多了一層輸出多少個符號的計算,把問題這樣想開了之後,首先,你要翻翻看,原來打印三角形時,你都用了什麼方法,如果從來沒做過這樣的題,那你麻煩了,不可能從這個題直接學到有用的東西了,怎麼辦,先去補基礎,把三角形弄穩了,再思考這道題:

*****
 ***
  *
 ***
*****

這個圖形,有幾個數學上的特點:
1, 每行最大符號號數與行數相等,也就是說,最大行如果是5個符號,那麼就有5行,那麼給多少符號才能出現7行呢?17+14=31,所以,給的符號數一定是+2*(2n-1),那麼這就是判斷給的數字能打印幾行的數學公式了,還有一個1我們單獨處理,因爲從數據歸納法中,我們知道,起始狀態總是有點點特別的,也正是因爲這點特別,遞歸才能完成,當 n=1時,不需要公式,當n=3時,累加上去就可以了,這時,我們就得到了計算使用多少字符的數學依據,如果你能想到這些,說明計算思維沒問題下面就是代碼的書寫:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
    int row,n,i,z,p,surplus,mid;
    char ch;
    scanf("%d %c",&n,&ch);
    for(row=1;row<=n;row+=2)//算出row(沙漏的行數)和surplus(剩餘的圖形數)
    {
        if(row==1)//一行的話,剩n-1
            surplus=n-1;
        else
            surplus-=2*row;//
        if(surplus<2*(row+2))
            break;
    }
    mid=row/2+1;//求出中間行
    //row行,最大row
    for(i=1;i<=row;i++)//一次把圖形打印
    {
        if(i==1) p=row;//求出第i行對應的圖形數
            else
            {
                if(i<mid) p-=2;//中間值以下,由p每次遞減2
                if(i>mid) p+=2;//中間值以上,由p每次遞增2
                if(i==mid) p=1;//中間值等於1
            }
            for(z=0;z<(row-p)/2;z++)//打印第i行的圖形前的空格,(滿足行數-i行的圖形數)/2
                printf(" ");
            for(z=0;z<p;z++)
                printf("%c",ch);
            printf("\n");
    }
    printf("%d",surplus);//打印剩餘的圖形數

}

測試結果:
測試結果
第二種方法:
因爲我在做題的時候發現了一個規律,最大行的圖形數=行數,且如果將其分成兩個等差數列的三角形,因爲an=2n-1,Sn=n^2,如果給出了圖形數,就可以將行數求出來,就直接從上到下打印兩遍,一遍:倒三角,用三個for()循環,一個大的用來控制行數,兩個小的平行,分別打印空格,字符。二遍:正三角,去掉一個尖,打印出來即可。
最後再用公式求出剩下的圖形數=總數-兩個等差數列和-1
代碼如下:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
    int a;
    char m;
    scanf("%d %c",&a,&m);
    int i,j,k;
    int b=sqrt((a+1)/2);//
    int c=2*b-1;
    int d=a-b*(1+c)+1;
    for(i=1;i<=b;i++)
    {
        for(k=1;k<i;k++)
        {
            printf(" ");
        }
        for(j=c-2*(i-1);j>0;j--)
        {
            printf("%c",m);
        }
        printf("\n");

    }
    for(i=1;i<b;i++)
    {
        for(k=b-i-1;k>0;k--)
        {
            printf(" ");
        }

        for(j=2*i+1;j>0;j--)
        {
            printf("%c",m);
        }
        printf("\n");

    }
    printf("%d",d);
    return 0;

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章