矩形的個數算法
在一個3*2的矩形中,能夠找到6個1*1的矩形,4個2*1的矩形3個1*2的矩形,2個2*2的矩形,2個3*1的矩形和1個3*2的矩形,總共18個矩形。給出A,B,計算能夠從中找到多少個矩形 編程
輸入:
本題有多組輸入數據(<10000),你必須處理到EOF爲止 數組輸入2個整數A,B(1<=A,B<=1000) 函數
輸出: 學習輸出找到的矩形數。spa
樣例:code輸入: blog
1 2
3 2 get
輸出:
3
18input
#include <stdio.h> int rectangle(int x,int y) { int i,j,sum,temp; for(i=1,sum=0,temp=0;i<=x;i++) { for(j=1;j<=y;j++) { temp = (x-i+1)*(y-j+1); sum += temp; } } return sum; } int main() { long int A[1000],B[1000],i; int rectangle(int x,int y); //printf("input A&B and end with 0\n"); for(i=0;i<1000;i++) { scanf("%d",&A[i]); if (A[i]==0) { break; } scanf("%d",&B[i]); } for(i=0;A[i]!=0;i++) { printf("%d\n",rectangle(A[i],B[i])); } return 0; }
寫完以後這位小朋友坦率地認可:
露珠不知道如何以EOF結尾..只好用0了...哪位指點下..
我告訴他,
不必用數組
while( scanf("%d%d", &A,&B)!=EOF )
{
//計算輸出矩形個數
}
因而他很快給出了新代碼:
#include <stdio.h> int rectangle(int x,int y) { int i,j,sum,temp; for(i=1,sum=0,temp=0;i<=x;i++) { for(j=1;j<=y;j++) { temp = (x-i+1)*(y-j+1); sum += temp; } } return sum; } int main() { long int A,B; int rectangle(int x,int y); printf("input A&B and end with EOF\n"); while(scanf("%d%d",&A,&B)!= EOF) { printf("%d\n",rectangle(A,B)); } return 0; }
此次好多了。不過他又有了新的困惑:
我修改爲這樣以後,好比我先輸入 2 3 跳出來 18,輸入eof 就一直跳 18 中止不了了...
總之就是一直跳最後一次出來的結果 ..
看來他不清楚EOF是怎麼回事,還覺得是在鍵盤上鍵入eof三個字符呢。
我告訴他:
EOF不是三個字符
而是一個符號常量
若是你用的是WIN系統
在行首輸入Control-Z試試
實際上EOF是在stdio.h中定義的一個宏,一般是這樣的
#define EOF (-1)
不過C語言並沒說EOF必定爲-1。
在鍵盤上是沒有這個EOF的,但在輸入流中遇到特殊的字符,scanf()函數的返回值能夠是EOF。那麼,這句話到底是什麼意思呢?
一般scanf()的返回值是一個非負整數。好比
int i;
scanf("%d", &i ) ;
若是你在鍵盤上鍵入的是123(一、二、3與%d相匹配),scanf("%d", &i )的值就爲1,由於爲1個變量賦了值;若是你在鍵盤上鍵的是abc(a與%d不匹配),scanf("%d", &i )的值就爲0,由於scanf沒法把"a"視爲十進制整數(%d),也沒法對它進行轉換,更沒法爲變量 i 賦值,也就是說scanf這種狀況下沒有爲任何變量賦值,因此返回值爲0。若是scanf()在輸入流中遇到的是某個特殊的字符(具體是哪一個字符與環境有關),則返回值爲EOF。
另外我告訴他:
把函數類型聲明
int rectangle(int x,int y);
寫在main()函數以內很傻
(應該把函數類型聲明)寫在函數外面
另外那個temp多餘
temp賦值爲零就更多餘
(由於能夠直接)
sum += (x-i+1)*(y-j+1);
就這樣,他再次進行了修改:
#include <stdio.h> int rectangle(int x,int y) { int i,j,sum,temp; for(i=1,sum=0;i<=x;i++) { for(j=1;j<=y;j++) { sum += (x-i+1)*(y-j+1);; } } return sum; } int rectangle(int x,int y); int main() { long int A,B; printf("input A&B and end with EOF\n"); while(scanf("%d%d",&A,&B)!= EOF) { printf("%d\n",rectangle(A,B)); } return 0; }
如今毛病少多了,不過仍是有一些。
首先, rectangle()函數定義的位置不妥,寫在main()定義的後面爲好。
其次,數據類型有問題,這個問題比較嚴重。
long int A,B;
這裏絕對沒有必要把A、B定義爲long類型,int類型足矣。因爲不當地把A、B定義成了long類型,因此代碼中的
scanf("%d%d",&A,&B)
和
rectangle(A,B)
這兩次調用都是錯的。雖然沒有產生錯誤的結果(估計在那個系統中long和int類型大小同樣),但實際上是瞎貓碰到死耗子,僥倖而已。
此外的兩處小瑕疵就是rectangle()函數定義中的temp變量忘記刪除了,循環體內刪除語句時不乾淨,有一「;」也忘記刪除了。
再有就是
sum += (x-i+1)*(y-j+1);
這個算法我沒看懂,不知道是否正確。
其實原來代碼已經改得差很少了,只剩下少量小錯和瑕疵。我在這裏只說一下個人算法:
個人算法是,窮舉出兩個點(P1,P2)的全部組合狀況,只要P1能夠是某個矩形的左上角,P2能夠是某個矩形的右下角(P1_X<P2_X,P1_Y<P2_Y),則構成了一個矩形。
1 /* 2 矩形的個數 3 在一個3*2的矩形中,能夠找到6個1*1的矩形,4個2*1的矩形3個1*2的矩形, 4 2個2*2的矩形,2個3*1的矩形和1個3*2的矩形,總共18個矩形。 5 給出A,B,計算能夠從中找到多少個矩形。 6 7 輸入: 8 本題有多組輸入數據(<10000),你必須處理到EOF爲止 9 輸入2個整數A,B(1<=A,B<=1000) 10 11 輸出: 12 輸出找到的矩形數。 13 14 樣例: 15 16 輸入: 17 1 2 18 3 2 19 20 輸出: 21 3 22 18 23 24 做者:薛非 25 出處:http://www.cnblogs.com/pmer/ 「C語言初學者代碼中的常見錯誤與瑕疵」系列博文 26 27 */ 28 29 #include <stdio.h> 30 31 int count( int , int ); 32 33 int main( void ) 34 { 35 int A , B ; 36 37 while ( printf( "輸入2個整數A,B(1<=A,B<=1000)" ), 38 scanf( "%d%d" , &A , &B )!= EOF 39 ) 40 { 41 printf( "%d\n" , count( A , B ) ); 42 } 43 44 return 0; 45 } 46 47 int count( int A , int B ) 48 { 49 int x1 , y1 ;//第一個點的座標 50 int x2 , y2 ;//第二個點的座標 51 int num = 0 ; 52 53 for ( x1 = 0 ; x1 <= B ; x1 ++ ) 54 for ( y1 = 0 ; y1 <= A ; y1 ++ )//窮舉第一個點的各類可能 55 for ( x2 = 0 ; x2 <= B ; x2 ++ ) 56 for ( y2 = 0 ; y2 <= A ; y2 ++ )//窮舉第二個點的各類可能 57 { 58 if ( x1 < x2 && y1 < y2 ) 59 num ++ ; 60 } 61 62 return num ; 63 }
這個代碼的不足之處在於沒有認真思考答案是否在int類型的表示範圍以內。在 飛鳥_Asuka 網友提出是否「時間複雜度比較大」的問題後,我一併考慮了這兩個問題。結論是:1.這個問題用數學的辦法很容易解決,不過採用這種方案對學習編程是不利的,由於求解太容易了;2.答案確實有可能超過int類型的表示範圍(假如int最大能表示到231-1的話)。這應該算是重構代碼中存在的一個BUG。我將在之後的博文中給出修正及數學解答。
在此感謝飛鳥_Asuka 網友的提醒。