c++でアルゴリズムの勉強をしています。
二分探索を用いて問題を解いていたのですが、わからないところがあります。
コード46行目の、配列kkにおいて、c * n + d とする意味がわかりません。
なぜ c * n + d とするのですか?kk[0]から順に埋めていくのではダメなのですか?
(問)
n枚の数字が書かれた紙がある。この中から一枚引いて、数字を見たのち元に戻す。これを4回行う。引いた数字をk1,k2,k3...,knとするとき、数字の和がmになる取り出し方が存在するか確認したい。存在するならyes,存在しないならnoと出力する。
[制約]
1 <= n <= 50
1 <= m <= 10^8
1 <= ki <= 10^8
該当のソースコード
c++
1ソースコード 2 3#include<iostream> 4using namespace std; 5 6const int MAX_N = 50; 7int n, m, k[MAX_N]; 8int kk[MAX_N * MAX_N]; 9 10//二分探索 11bool binary_search(int x) { 12 //配列kkについて考える。xの存在し得る範囲は、kk[1],kk[2],...,kk[n*n-1] 13 //最小の添え字 14 int min = 0; 15 //最大添え字 16 int max = n * n - 1; 17 //中央の要素番号 18 int mid; 19 20 //最大値と最小値が一致するまで比較する 21 while (min <= max) { 22 mid = (min + max) / 2; 23 24 //一致するか比較 25 if (kk[mid] == x) return true; 26 //目的値が中央値よりも上なら最小値を中央値の1個上に設定 27 else if (kk[mid] < x) min = mid + 1; 28 //目的値が中央値よりも下なら最大値を中央値の1個下に設定 29 else if (kk[mid] > x) max = mid - 1; 30 } 31 32 return false; 33} 34 35int main() { 36 37 //標準入力 38 scanf("%d %d", &n, &m); 39 for (int i = 0; i < n; i++) { 40 scanf("%d", &k[i]); 41 } 42 43 //k[c] + k[d]のとり得る値を列挙する 44 for (int c = 0; c < n; c++) { 45 for (int d = 0; d < n; d++) { 46 kk[c * n + d] = k[c] + k[d]; 47 } 48 } 49 50 51 sort(kk, kk + n * n); 52 53 bool f = false; 54 55 for (int a = 0; a < n; a++) { 56 for (int b = 0; b < n; b++) { 57 //内側の2つ代わりに二分探索を用いる 58 if (binary_search(m - k[a] - k[b])) { 59 f = true; 60 } 61 } 62 } 63 64 if (f) puts("Yes"); 65 else puts("No"); 66} 67 68
回答1件
あなたの回答
tips
プレビュー