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