B - Great Ocean View 解説 by TumoiYorozu


この解説は、C++ に入門したばかりの中高生レベルを想定して、考察の方法、コードの書き方の解説をします。

今回は、配列を知らない人向けに、配列を使わずに繰り返し文だけで解く方法を解説します。

ヒント1: 数式の読み方

問題文中に「\(H_1\le H_i, H_2 \le H_i, ...,\) かつ \(H_{i-1} \le H_i\)」という数式が出てきます。

これは \(i=4\) として具体的に書くと 「\(H_1\le H_4,\) かつ \(H_2 \le H_4\) かつ \(H_3 \le H_4\)」と読むものであり、これを i を一般化して更に省略した書き方が問題文の数式の意味です。また \(\le\)\(\leqq\) と同じ意味です。

ようするに、「ある山に関して、それより手前のどの山よりも同じか大きいとき、その山頂の旅館から海を眺めることができます」と言う意味です。

ヒント2: 解き方の方針の考え方ヒント

手前のどの山よりも大きいような山の個数を求めれば良いです。

『手前のどの山よりも大きい』の判定方法を考えてみましょう。

この判定を行う時、『手前の山全て』と自分の山を比較する必要は実はありません。

ヒント3: 解き方の方針

『手前のどの山よりも大きい』かの判定は、『手前の山全て』と自分の山を比較する必要はなく、実は『手前の中で一番高い山の高さ』と自分の山の高さを比較すれば良いです。

これをヒントに実装できないか、チャレンジしてみましょう。

ヒント4: 繰り返し文の復習

for(int i = 0; i < N; i++) で N 回のループを表現できます。

ヒント5: 繰り返し文で入力 h を順番に読む方法の復習

以下の様に書くと、入力 N と、山の高さ h を読み込むことができます。

#include <bits/stdc++.h>
using namespace std;
int main(){
    int N;
    cin >> N;
    
    ~~処理①~~
    for(int i = 0; i < N; i++) {
        int h;
        cin >> h;
        ~~処理②~~
    }
    ~~処理③~~
}

次のヒントは、『手前の中で一番高い山の高さ』の記録する方法です。

ヒント6

処理① で現在一番高い山の高さを入れる変数 high を用意して、最初はダミー値としてどんな高さよりも低い値である 0 を入れておくと良いでしょう。

処理② では、if 文を用いることで、high を更新するコードを書きます。

ヒント7: ヒント6の実装例

ヒント6は、具体的に以下の様に書くことができます。

#include <bits/stdc++.h>
using namespace std;
int main(){
    int N;
    int high = 0;
    cin >> N;
    
    ~~処理①~~
    for(int i = 0; i < N; i++) {
        int h;
        cin >> h;

        // もしも、この山が今までで一番高い山だったら
        if (high < h) {
            high = h;
            ~~処理②~~
        }
    }
    ~~処理③~~
}

さて、ヒント2 で『手前のどの山よりも大きいような山の個数を求め』れば良いと分かったので、これを実現するコードを書きましょう。

ヒント8: デバッグ(間違い探し)のヒント

このヒントはオマケです。

繰り返し文を使うときに答えが合わないときは、ループの中で変数の中身を表示してみると良いです。

例えば以下のコードは(ほとんど正解に近いのですが)間違いを含んでおり、入力例1は3が正解のところ2が出力されてしまいます。

そこで、18行目の様に、ループの中に色々な変数の値を出力してみて、毎回どの様に値が変化しているのか観察してみると良いです。

#include <bits/stdc++.h>
using namespace std;
int main(){
    int N;
    int high = 0;
    cin >> N;

    int ans = 0;
    for(int i = 0; i < N; i++) {
        int h;
        cin >> h;
        
        if (high < h) {
            high = h;
            ans += 1;
        }

        // デバッグのために、毎回どの様に値が変化しているのか確かめる。
        cout << "i=" << i << " high=" << high << " ans=" << ans << endl;
    }
    cout << ans << endl;
}

このデバッグのためのコードを実行すると、以下のような結果が得られます。

i=0 high=6 ans=1
i=1 high=6 ans=1
i=2 high=6 ans=1
i=3 high=8 ans=2
2
さて、一体何が間違えているのでしょうか…?
解答コード

実際の提出のリンクはこちら

#include <bits/stdc++.h>
using namespace std;
int main(){
    int N;
    int high = 0;
    cin >> N;

    int ans = 0;
    for(int i = 0; i < N; i++) {
        int h;
        cin >> h;

        // もしも、この山が今までで一番高い山だったら
        if (high <= h) {
            high = h;
            ans += 1;
        }
    }
    cout << ans << endl;
}

14~17 行目は、以下のように2つに分けて書いても大丈夫です。

        if (high <= h) {
            ans += 1;
        }
        if (high < h) {
            high = h;
        }
        if (high < h) {
            high = h;
        }
        if (high == h) {
            ans += 1;
        }

投稿日時:
最終更新: