1. 程式人生 > >A. Vasya and Book

A. Vasya and Book

題目原址

http://codeforces.com/contest/1082/problem/A

題目內容

一共n頁書,現在位於第x位,想要看第y頁,每次只能翻d頁,注意總能翻到第1頁和第n頁。

Vasya想知道自己能否在經過無數次翻書後 看到第y頁的內容。

如果可以,請給出最少需要翻幾次書。

題目解析

類似一個模除的問題。

首先思考無法翻到第y頁的情況,即:

①直接翻翻不到

②在到達第1頁和第n頁後也翻不到

對應的式子引出的是:

直接翻不到:

abs(y - x) % d != 0

第1頁翻不到:

abs(y - 1) % d != 0

第n頁翻不到:

abs(n - y) % d != 0

因此翻不到的情況很好判斷。注:以下簡記 左不通 和 右不通 分別代表第一頁翻不到和第n頁翻不到。

再看最小翻閱次數,這裡可以詳盡的判斷所有情況,也可以統一完成,本人採用的是詳盡的判斷。

將所有可能性列舉出來,即左不通而右通,那麼最短翻閱只有右側的一種方式。

對應的程式碼部分為:

if(abs(y - 1) % d != 0){    //左側不通 
                //int temp = need(x, y, d);
                if(abs(n - y) % d != 0){    //右側不通 
                    puts("
-1"); continue; } else { count += need(x, n, d); count += need(n, y, d); cout << count << endl; continue; } }

其中,need()函式用來計算從x到y在每次翻閱d的情況下直接到達需要的翻閱次數,如下:

int need(int x, int y, int d){    //3 - 6 3
    if(abs(y - x) % d == 0){
        return abs(y - x) / d;
    }
    else {
        return abs(y - x) / d + 1;
    }
} 

當右側不通,而左側通的時候,情況類似上述:

else if(abs(n - y) % d != 0){    //右側不通 
                //int temp = need(x, y, d);
                count += need(x, 1, d);
                count += need(1, y, d);
                cout << count << endl;
                continue;
}

而當左右都可通過的時候,只需計算左右兩種方式中翻閱數的最小者即可。

else{
            int left = need(x, 1, d) + need(1, y, d);
            int right = need(x, n, d) + need(n, y, d);
            count = min(left, right);
            cout << count << endl;
            continue;
}

題目也可以將不通返回正無窮,從而在返回最小值的過程中失效,減少判斷。

題目總結

很簡單的題目,沒有考察到演算法知識,只是考驗程式設計者對於多種判斷情況的處理。做題時應先想好思路再完成。