2015年12月4日 星期五

d057:11494 - Queen (36)

d057: 11494 - Queen (36)

更新時間:2016/12/22

內容
  西洋棋中有幾個子的走法滿特別的,其中一個就是皇后。她可以循垂直、水平、或對角線的方向隨她走幾格,如下圖 (黑點表示皇后可以一步走到的格子):
    西洋棋大師 Kary Gasparov 提出了一新的問題:在標準的西洋棋空棋盤 (8 x 8 棋盤) 上擺一個皇后,它要走幾步才能走到某個特定的格子?Kary 已經找到了某些情況的解,但有些情況他卻解不出來。因此他請你幫他寫一個程式來解這個問題。

輸入說明
  輸入檔包含了好幾筆測試資料。每筆測試資料只有一行,其中含有整數 X1, Y1, X2 及 Y2 (1 ≤ X1, Y1, X2, Y2 ≤ 8)。皇后從座標 (X1, Y1) 的格子開始,必須在座標 (X2, Y2) 的格子結束。在棋盤中的行由左至右編號為 1 到 8,列則由上至下編號為 1 到 8。位於第 X 列第 Y 行的格子其座標為 (X, Y)。 輸入的結尾以四個由空白隔開的 0 來表示。

輸出說明
  對於每筆測試你的程式要印出一行,該行含有一個整數,表示皇后要走到新的位置至少需要幾步。

範例輸入
  4 4 6 2
  3 5 3 5
  5 5 4 3
  0 0 0 0

範例輸出
  1
  0
  2

提示

背景知識
  迴圈




想一想,再看解答~

我的解題想法

  分析後,我們要用水平距離與垂直距離來判定四種情況:

    1.在同一點,走 0 步:
      水平距離=垂直距離=0

    2.在斜線上,走 1 步:
      水平距離=垂直距離≠0

    3.在直線上,走 1 步:
      水平距離=0≠垂直距離 或 垂直距離=0≠水平距離

    4.以上三種都不是,走 2 步。


程式碼
#include <stdio.h>
int main(void){
    int x1,y1,x2,y2;
    scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    while(x1+x2+y1+y2){
        x1 = x1 - x2;
        x1 = (x1^(x1>>31))-(x1>>31);
        y1 = y1 - y2;
        y1 = (y1^(y1>>31))-(y1>>31);
        if(x1^y1){
            printf("%d\n", x1*y1 ? 2 : 1);
        }else{
            printf("%d\n", x1+y1 ? 1 : 0);
        }
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    };
    return 0;
}
程式碼解析
#1:引入標準輸入/輸出串流。
#2:主程式開始,回傳引數int,沒有參數。
#3:宣告4個整數(int)變數「x1」、「x2」、「y1」、「y2」,範圍–2,147,483,648 到 2,147,483,647。
#4:從標準輸入讀取格式化數據。讀取4個整數(%d%d%d%d),依序指定值給「x1」、「x2」、「y1」、「y2」。
#5:迴圈 while 開始。利用 C 語言特性,當 x1+x2+y1+y2 等於 0 時,為 false;當 x1+x2+y1+y2 不等於 0 時,為 true。
#6:計算水平差,存回變數「x1」。
#7:計算水平差的絕對值,存回變數「x1」。因為 OnlineJudge 平台的(int)型別為 32 位元,所以第 32 個位元記錄正負號,再利用「二進制」資料正負數的互補性,求得絕對值。
#8:計算垂直差,存回變數「y1」。
#9:計算垂直差的絕對值,存回變數「y1」。因為 OnlineJudge 平台的(int)型別為 32 位元,所以第 32 個位元記錄正負號,再利用「二進制」資料正負數的互補性,求得絕對值。
#10:邏輯判斷式 if 開始。判斷水平與垂直距離是否相等(位元運算 x1^y1),如果相等,為 false;如果不相等,為 true。
#11:將格式化數據顯示到標準輸出。輸出1個整數並換行(%d\n)「x1*y1 ? 2 : 1」。如果 x1*y1 不等於 0,輸出 2 ;否則輸出 1。
#12:邏輯判斷 else 開始。
#13:將格式化數據顯示到標準輸出。輸出1個整數並換行(%d\n)「x1+y1 ? 1 : 0」。如果 x1+y1 不等於 0,輸出 1 ;否則輸出 0。
#14:邏輯判斷式 if 結束。
#15:從標準輸入讀取格式化數據。讀取4個整數(%d%d%d%d),依序指定值給「x1」、「x2」、「y1」、「y2」。取下來的值,要給 while 判斷是否有資料。
#16:迴圈 while 結束。
#17:主程式回傳整數「0」。
#18:主程式結束。