B - Great Ocean View 解説 by TumoiYorozu
この解説は、C++ に入門したばかりの中高生レベルを想定して、考察の方法、コードの書き方の解説をします。
今回は、配列を知らない人向けに、配列を使わずに繰り返し文だけで解く方法を解説します。
問題文中に「\(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\) と同じ意味です。 ようするに、「ある山に関して、それより手前のどの山よりも同じか大きいとき、その山頂の旅館から海を眺めることができます」と言う意味です。 手前のどの山よりも大きいような山の個数を求めれば良いです。 『手前のどの山よりも大きい』の判定方法を考えてみましょう。 この判定を行う時、『手前の山全て』と自分の山を比較する必要は実はありません。
『手前のどの山よりも大きい』かの判定は、『手前の山全て』と自分の山を比較する必要はなく、実は『手前の中で一番高い山の高さ』と自分の山の高さを比較すれば良いです。 これをヒントに実装できないか、チャレンジしてみましょう。 以下の様に書くと、入力 N と、山の高さ h を読み込むことができます。 次のヒントは、『手前の中で一番高い山の高さ』の記録する方法です。
処理① で現在一番高い山の高さを入れる変数 処理② では、if 文を用いることで、 ヒント6は、具体的に以下の様に書くことができます。 さて、ヒント2 で『手前のどの山よりも大きいような山の個数を求め』れば良いと分かったので、これを実現するコードを書きましょう。
このヒントはオマケです。 繰り返し文を使うときに答えが合わないときは、ループの中で変数の中身を表示してみると良いです。 例えば以下のコードは(ほとんど正解に近いのですが)間違いを含んでおり、入力例1は そこで、18行目の様に、ループの中に色々な変数の値を出力してみて、毎回どの様に値が変化しているのか観察してみると良いです。 このデバッグのためのコードを実行すると、以下のような結果が得られます。
14~17 行目は、以下のように2つに分けて書いても大丈夫です。 ヒント1: 数式の読み方
ヒント2: 解き方の方針の考え方ヒント
ヒント3: 解き方の方針
ヒント4: 繰り返し文の復習
for(int i = 0; i < N; i++)
で N 回のループを表現できます。 ヒント5: 繰り返し文で入力 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 を入れておくと良いでしょう。high
を更新するコードを書きます。
ヒント7: ヒント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;
~~処理②~~
}
}
~~処理③~~
}
ヒント8: デバッグ(間違い探し)のヒント
3
が正解のところ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 << "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;
}
if (high <= h) {
ans += 1;
}
if (high < h) {
high = h;
}
if (high < h) {
high = h;
}
if (high == h) {
ans += 1;
}
投稿日時:
最終更新: