【C++】グリッド上のオブジェクトを発見するのに必要なスキャン回数を求めるコード
ここでは、m × n のサイズを持つグリッドが与えられていると仮定します。あるオブジェクトがセル (ix, iy) に配置されており、開始位置 (sx, sy) からスキャンを実行して、このオブジェクトを発見することが目的です。
スキャンのアルゴリズムは、グリッド上のセル (i, j) に位置しているとき、i 行目と j 列目全体をスキャンします。オブジェクトが見つかった時点でスキャンは終了し、まだ見つからない場合は、ポインタがセル (i + 1, j + 1) に移動して同じ要領で再度スキャンを行います。この処理を、オブジェクトが見つかるまで繰り返します。各位置情報が与えられたとき、アルゴリズムがオブジェクトを発見するまでに何回のスキャンが必要かを求めましょう。
たとえば、入力が n = 20、m = 20、sx = 3、sy = 2、ix = 12、iy = 4 である場合、出力は 2 となります。
解き方の手順
この問題を解くには、以下の手順に従います。
- t1 := (sx <= ix であれば ix − sx、そうでなければ 2 * n − ix − sx)
- t2 := (sy <= iy であれば iy − sy、そうでなければ 2 * m − iy − sy)
- t1 と t2 のうち小さい方の値を出力する
ポイントは、スキャンポインタが対角方向へ進んでいくという仕組みを利用することです。行方向と列方向のそれぞれについて、オブジェクトが存在する行・列に到達するまでの移動回数を計算します。どちらか早い段階でオブジェクトが検知されるため、両者の最小値が答えとなります。
C++による実装例
理解を深めるために、以下の実装例を見てみましょう。
#include <bits/stdc++.h>
using namespace std;
#define N 100
void solve(int n, int m, int sx, int sy, int ix, int iy) {
int t1 = (sx <= ix ? ix - sx : 2 * n - ix - sx);
int t2 = (sy <= iy ? iy - sy : 2 * m - iy - sy);
cout<< min(t1, t2);
}
int main() {
int n = 20, m = 20, sx = 3, sy = 2 , ix = 12, iy = 4;
solve(n, m, sx, sy, ix, iy);
return 0;
}
入力
20, 20, 3, 2 , 12, 4
出力
2
このように、開始位置 (3, 2) からスキャンを開始すると、わずか 2 回のスキャンでオブジェクト (12, 4) を発見できることが確認できます。行・列それぞれの到達ステップ数を比較するだけのシンプルな計算で答えが得られるため、非常に効率的なアプローチといえるでしょう。
-
C++で文字列の部分文字列の総数を求める方法を解説
この記事では、与えられた文字列から作成できる空でない部分文字列の個数を求める方法について解説します。入力 : string = "moon" 出力 : 10 説明 : 部分文字列は m、o、o、n、mo、oo、on、moo、oon、moon の 10 個です。 入力 : string = "yellow" 出力 : 21解法のアプローチ文字列の長さを n とします。上の例からも分かるように、考えられるすべての部分文字列の個数を求めるには、長さ n、(n-1)、(n-2)、(n-3)、……2、1 の部分文字列の個数を順に加算していく必要があります。部分文
-
C++で列車の停車駅の組み合わせ数を求める方法
地点XとYの間にはn個の中間駅があるとします。ここで、「どの2つの停車駅も隣り合わない」という条件のもとで、s個の駅に停車する列車の配置方法が何通りあるかを求める問題を考えてみましょう。この記事では、停車駅の組み合わせ数を求めるためのアプローチを段階的に詳しく解説します。この問題は、本質的には組合せ論の問題であり、s個の停車駅の選び方の総数を求めることになります。 問題を解くアプローチ まず具体例として、中間駅が8個あり、そのうち3個の駅に停車させたい場合を考えてみます。 n = 8, s = 3 このとき、列車が停車できない駅は(n − s)、つまり5個残ることになります。 停車できない