C++で長さa、b、cのセグメントの最大数を求める方法
正の整数Nが与えられたとき、そのNを長さa、b、cの線分に分割して、最大で何個のセグメントを作成できるかを求めるのが本課題です。
具体例を使って、何をすべきか見ていきましょう。
入力 − N=8, a=3, b=1, c=2
出力 − 8
説明 − Nは長さbのセグメント8個に分割でき、これが作成可能なセグメントの最大数となります。
入力 − N=13, a=2, b=7, c=3
出力 − 6
プログラムで使用するアプローチ
この問題は動的計画法(DP)を用いて効率的に解くことができます。配列MaxSeg[i]には、長さiを作成するために必要なセグメントの最大数を格納します。具体的な手順は以下の通りです。
MaxSegment()関数内で、int型の配列MaxSeg[N+1]を宣言し、すべての要素を-1で初期化します。-1は「その長さを作成できない」ことを意味します。
0番目のインデックスには0を設定します。長さ0にはセグメントが存在しないためです。
i=0からi<Nまでループし、MaxSeg[i] != -1であるかどうかを確認します。
上記の条件を満たす場合、さらにi + a <= Nであるかをチェックし、条件を満たしていればMaxSeg[i + a] = max(MaxSeg[i] + 1, MaxSeg[i + a])を設定します。
長さbとcについても同様の処理を繰り返します。
ループ終了後、MaxSeg[N]を返します。
例
#include <bits/stdc++.h>
using namespace std;
int MaxSegment(int N, int a,int b, int c){
/* 各インデックスが持つセグメントの最大数を格納 */
int MaxSeg[N + 1];
// 初期化
memset(MaxSeg, -1, sizeof(MaxSeg));
// 0番目のインデックスはセグメント数0
MaxSeg[0] = 0;
// nまでの各セグメントを走査
for (int i = 0; i < N; i++){
if (MaxSeg[i] != -1){
if(i + a <= N ){
MaxSeg[i + a] = max(MaxSeg[i] + 1, MaxSeg[i + a]);
}
if(i + b <= N ){
MaxSeg[i + b] = max(MaxSeg[i] + 1, MaxSeg[i + b]);
}
if(i + c <= N ){
MaxSeg[i + c] = max(MaxSeg[i] + 1, MaxSeg[i + c]);
}
}
}
return MaxSeg[N];
}
int main(){
int N = 13, a = 2, b = 7, c = 3;
cout << MaxSegment(N, a, b, c);
return 0;
}
出力
上記のコードを実行すると、以下の出力が得られます。
6
-
C++でN個のセグメントを使って7セグメントディスプレイに表示できる最大の数を求める方法
問題の概要 この記事では、7セグメントディスプレイに対してN個のセグメントを使用したときに、表示できる最大の数を求める方法を解説します。 まず、具体例を使って何をすべきかを確認しましょう。 入力 − N=5 出力 − 71 説明 − この場合、最大の数は7セグメントディスプレイ上で次のように表示されます。 入力 − N=6 出力 − 111 アルゴリズムのアプローチ この問題は、次の3つの場合に分けて考えることができます。 ケース1 −Nが0または1の場合、どの数字も表示できません。 ケース2 −Nが奇数の場合です。奇数個のセグメントで表示できる数字は2、3、5、7、8であり、その中で最
-
【C++】連結リスト内で指定した数Kで割り切れる最大要素と最小要素を求める方法
連結リストとは 連結リスト(リンクリスト)は、要素同士がポインタで連結された線形データ構造です。各要素(ノード)は「データ部分」と「次の要素を指すリンク(ポインタ)」を持ち、メモリ上の連続していない場所に配置されることもあります。 本記事では、データ部分と次ノードへのリンクを持つ片方向連結リストと、整数Kが与えられます。目的は、連結リスト内の要素のうち「Kで割り切れる」要素の最大値と最小値を見つけることです。線形連結リストは一方向にしか走査できないため、ヘッド(先頭)ノードから順に各ノードを訪問し、そのデータ部分がKで割り切れるかどうかを判定します。現在のノードの値が、それまでに見つかった最