数値を複数の群に分ける最適な組み合わせを求める方法

このQ&Aのポイント
  • 数値を複数の群に分ける方法について説明します。与えられた数値列で隣り合う数値しか同じ群に含めることはできず、各群の合計値が最も均等になる組み合わせを求めることが目標です。
  • 例えば、数値列{5,2,7,12,6,15,4}を3つの群に分ける場合、{5,2,7},{12},{6,15,4}という組み合わせが最も均等です。
  • 実際の問題では、組み合わせの数が増えると計算時間に影響するため、全ての組み合わせを試さずに最適な組み合わせを求める方法を提示してください。
回答を見る
  • ベストアンサー

数値を複数の群に分ける最適な組み合わせを求める方法

次のような問題をCで記述するにはどのようにすればいいでしょうか? 要素数が不定の整数値配列がある。 この配列の各要素を、与えられた個数の群に分ける。 条件として、与えられた数値列で隣り合う数値しか同じ群に含めることは出来ない。 例: 数値列は{5,2,7,12,6,15,4} 群の個数を3とする。 (1) {5,2},{7,12,6},{15,4} (2) {5},{2,7},{12,6,15,4} (3) {5,2,7},{12},{6,15,4} ・・・ と複数の組み合わせがある。 これらの組み合わせのうち、各群の合計値が最も均等になるような組み合わせを求める。最大値と最小値の差が最小となる組み合わせを最も均等と考える。 上の例であれば、各群の合計値と、合計値の最大値と最小値の差は、 (1) {5,2},{7,12,6},{15,4} ==> 7,25,19 (25-7=18) (2) {5},{2,7},{12,6,15,4} ==> 5,9,37 (37-5=32) (3) {5,2,7},{12},{6,15,4} ==> 14,12,25 (25-12=13) ☆ のようになり、この3つの中で最も均等なのは (3) {5,2,7}{12}{6,15,4} となる。 実際は、これ以外の組み合わせでより均等となるものがあるかと思います。 この問題そのものが必要なわけではなく、この結果を利用して別のある問題を解決しようとしています。 数値の数が増えると組み合わせの数も大幅に増えて計算時間に影響すると思います。 全ての組み合わせを試すことなく答えにたどり着く方法があれば、考え方だけでも提示頂ければと思います。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.27

>回答No.23 amanojaku1 「2018/06/15 03:48:47」の時点で修正しました。 それ以前にコピーしている場合は注意して下さい。 数値を複数の群に分ける最適な組み合わせを求める方法 http://ashtarte.pa.land.to/utf8/smt.cgi?r+sara/&bid+000000DC&tsn+000000DC&bts+2018/06/15%2002%3A04%3A46&

katorea21
質問者

お礼

コメント追加して頂きありがとうございます。今頑張って理解しているところですが、何となく分かってきました。 それにしても2進数の数学的特徴をうまくこの問題に当てはめるという発想が凄いですね。問題の本質は順列のパターンを網羅することですが、私は再帰を使うイメージしかなかったです。

その他の回答 (91)

回答No.92

>変数がレジスターに割り当てられてないと、パイプライン・ハザード(パイプラインの停止状態)が発生するので、その場合は最大値最小値を条件付分岐で記述した方がパフォーマンスが良くなります。 これは最大値最小値の場合であって、他の処理でも同様ではありません。

回答No.91

>変数がレジスターに割り当てられてないと、パイプライン・ハザード(パイプラインの停止状態)が発生するので、その場合は最大値最小値を条件付分岐で記述した方がパフォーマンスが良くなります。 CPUのレジスターの数に依存し、コンパイラーのレジスターの割り当てに依存し、パフォーマンスの良し悪しが変わります。

回答No.90

条件付分岐で分岐予測が外れた場合、パイプラインのStall(ストール:停止状態)が発生します、これは製造ラインの製品の製造が失敗し、それを破棄すると言うことになります。 それなら条件付分岐自体を使わないで記述すれば製品の破棄はなくなります。 その どちらかが筋立てとしてスマートか と言うだけの話です。 ただし、実際は それほど単純ではなく、変数がレジスターに割り当てられてないと、パイプライン・ハザード(パイプラインの停止状態)が発生するので、その場合は最大値最小値を条件付分岐で記述した方がパフォーマンスが良くなります。 これらはパフォーマンスの良し悪しが変わるだけで、ハードに依存して実行結果が変わる訳ではありません。 そもそも条件付分岐で分岐予測が外れた場合、製品の製造が失敗して(そして その製品を破棄して)いますが、それでもハードに依存して実行結果が変わる訳ではありません。

回答No.89

>gmmin = (gmt[m] & (-(long long)(gmt[m]<gmmin))) | (gmmin & ~(-(long long)(gmt[m]<gmmin))); >gmmax = (gmt[m] & (-(long long)(gmmax<gmt[m]))) | (gmmax & ~(-(long long)(gmmax<gmt[m]))); 「<」:係演算子、「&、|、~」:ビット演算子、「-」:四則演算子と、どれも非常に単純な演算子だけです、これでハードに依存したりしません。 もちろんBasic系のように「(long long)(gmt[m]<gmmin))」が真の時に「-1」になる場合はマイナスしてはダメですが。

回答No.88

>変数がレジスターに割り当てられてないと、パイプライン・ハザード(パイプラインの停止状態)が発生する これは、変数がレジスターに割り当てられてないと、(コードを条件付分岐自体を使って記述しようが、コードを条件付分岐自体を使わないで記述しようが)パイプライン・ハザード(パイプラインの停止状態)が発生する、と言う意味です。

回答No.87

>それなら条件付分岐自体を使わないで記述すれば製品の破棄はなくなると言うだけの事です。 つまり、条件付分岐自体を使わないで記述した方が、コードとしては筋立てが良いと言うことです。 ただし、実際は それほど単純ではなく、変数がレジスターに割り当てられてないと、パイプライン・ハザード(パイプラインの停止状態)が発生するので、その場合は最大値最小値を条件付分岐で記述した方がパフォーマンスが良くなります。

回答No.86

>それってかなり環境依存ではないでしょうか?CPUの構造やバスの通信規格など複合的なハード条件に左右されると思います。 もしかして、Stall(ストール:停止状態)云々のことを言ってますか? あれはパイプラインの問題です。 条件付分岐で分岐予測が外れた場合、パイプラインのStall(ストール:停止状態)が発生します、これは聖像ラインの製品の製造が失敗し、それを破棄すると言うことになります。 それなら条件付分岐自体を使わないで記述すれば製品の破棄はなくなると言うだけの事です。 ただし、実際は それほど単純ではなく、変数がレジスターに割り当てられてないと、パイプライン・ハザード(パイプラインの停止状態)が発生するので、その場合は最大値最小値を条件付分岐で記述した方がパフォーマンスが良くなります。 これらはハードの話に聞こえるかも知れませんが(まあ実際ハードの話ですが)、ハードに依存して実行結果が変わる訳ではありません(パフォーマンスが良くなるか悪くなるかと言うだけの話です)。 そもそも条件付分岐で分岐予測が外れた場合、製品の製造が失敗していると言うことに注意して下さい、それでもハードに依存して実行結果が変わる訳ではありません。

回答No.85

>「(long long)(gmt[m]<gmmin))」が真の時に「1」なら(signedなら)マイナスにすれば「-1」と言うだけのことです((signedなら)「-1」と言うのは全ビット「1」と言う事)。 CPUは整数の加算・減算を「2の補数」で計算します(これはCPUの普遍的な仕様と言って良いほどの決まりごと)。 「2の補数」で「-1」と言うのは全ビット「1」と言う事です。

回答No.84

>CPUのレジスターの数に依存し、コンパイラーのレジスターの割り当てに依存します(自分でregister指定子を指定することでパフォーマンスが改善する可能性があるかもしれないと言う視点を持っていて損はないでしょう)。 パフォーマンスの良し悪しが、CPUのレジスターの数に依存し、コンパイラーのレジスターの割り当てに依存すると言う意味で、コード自体はハードに依存してません。

回答No.83

>>それってかなり環境依存ではないでしょうか?CPUの構造やバスの通信規格など複合的なハード条件に左右されると思います。 >CPUのレジスターの数に依存し、コンパイラーのレジスターの割り当てに依存します(自分でregister指定子を指定することでパフォーマンスが改善する可能性があるかもしれないと言う視点を持っていて損はないでしょう)。 コード自体はハードに依存してません。 「(long long)(gmt[m]<gmmin))」が真の時に「1」なら(signedなら)マイナスにすれば「-1」と言うだけのことです((signedなら)「-1」と言うのは全ビット「1」と言う事)。 よってコード自体は全くハードに依存してません。 もちろんBasic系のように「(long long)(gmt[m]<gmmin))」が真の時に「-1」になる場合はマイナスしてはダメですが。

関連するQ&A

  • 2つの群の2値の平均値が最小となる組み合わせを

    いつもお世話になっております。 少しややこしい内容なので説明が分かりにくくなってしまうと思うので忖度に期待して質問させていただきます。 図のように1群、2群にA、BのデータがNo1から順に最大30個(2群は4~15個)のデータの 1)A(1)列の2値の平均値と2群のA(2)列の2値の平均値の差が最小になる2つを見つける。 2)同様にB(1)列の2値の平均値とB(2)列の2値の平均値の差が最小になる組み合わせを見つける。 3)1)と2)の合計が最小になる組み合わせのデータNoを知りたいのです。 例えばイメージ(入力数値は無視)として1群からデータNo4とNo8を選んだ時に、2群のNo20とNo27を組み合わせるとA、Bの2値の平均値の誤差が最小値になる組み合わせを知りたいのです。 現在は差の絶対値を行列数式でA(1)のデータNo1とA(2)のNo16からNo30までの総当たりで、同様にB1についても総当たりで求めて、両方の差の和の一番小さくなるケースを探しているのですが精度(やり方)が悪いのでお知恵拝借したく、わかりにくくお手数ですが宜しくお願いします。

  • 列の数値群の数値の抽出方法(VBA)

    エクセルVBAでお願いします。 今、B列にRange(Cells(3,2),Cells(I.2))の範囲にランダムな実数値が 格納されているとします。(Iは変数) この数値群から、正の実数で最小値、または負の実数で最大値を抽出したいのですが、どのようなコードを組めばよいでしょうか。 数値群は大小順ではなくランダムに並んでいるとします。お願いいたします。数値群の数は約20000個あります。

  • 群数列です

    1から順に自然数を並べて次のように群にわける。 1/2,3/4,5,6,7/8,9,…/…… ただし第n群が含む数の個数は2のn-1乗個である。 第n群に含まれる数の総和が10000を超えない最大のnを求めよ。 という問題なんですが、わかる方解答お願いします。

  • n次対称群の要素を互換で表すときの最大個数

    n次対称群(置換群)の要素を、隣接互換で表すときの最大個数は、転倒数が最大のものあり、 C(n-1,2)=Σ[k=1,n-1]k=n(n-1)/2 ただし、Cは二項係数。 では、n次対称群(置換群)の要素を、(隣接とは限らない)互換で表すときの最大個数は何なのでしょうか。

  • 複数の数値を組み合わせ5000(少しオーバーでもよい)に纏める方法

    複数の数値を組み合わせ5000(少しオーバーでもよい)に纏める方法 ■使用機器 win7 Office2007 エクセル ■教えて戴きたい内容 ◎A列に通し番号(1~65)B列に10~1000台の数値がランダムに記載されています。例えば98  1245  3866・・・・と言うように。 ◎これ等65の内の何れかの複数の数値を組み合わせ「幾つかの5000」の数値に纏めたい。 5000ぴったりであれば理想的であるが、500を少しオーバーしても良い。(計算できる最小オーバー数値でよい)  ◎このような事ができる方法をご存知の方のご教示を御願いたします。 ■コメント ◎私の現状の力量はごく簡単な関数(SUM関数程度)です。あまり高等な関数は理解しかねます。比較的簡単な操作方法があれば幸甚です。

  • C♯の配列について

    C♯でプログラムを作っているのですが、配列の要素数の最大値と最小値の求め方がわかりません。配列の値の最大値の求め方は調べれば出てくるのですが、要素数の最大値等は調べてもわかりませんでした。 例えば下記のような配列があった場合 int[,,] a =new int[100,100,100] a[2,3,6]=1 a[4,5,9]=1 a[13,46,79]=1 a[8,15,45]=1 a[1,33,68]=1 それぞれの要素数の最小値1、3、6、最大値13、46、79は どのようにプログラムで求めればいいのでしょうか? よろしくお願いします。

  • 数値データの規格化

    数値データの規格化の方法を教えてください 最大値がXmax,最小値がXminであるN個のデータ群 Xn(n=1,2,3・・・)があります. このデータを最大値がA,最小値がBとなるように規格化したいです. 元のデータ群Xnで最大値を1,最小値を0となるような規格化は分かるのですが, そこから,最大値をA,最小値をBとなるように変換する方法が分かりません. よろしくお願い致します.

  • 算数パズルを教えてください

    算数パズルを教えてください 子供(小4)が持って帰ってきた問題です。 さっぱりわからないので解き方も含めて教えてください。 以下問題です・・・ 3×3=9マスの枠内に以下の27個の数字のうち、重複しない9つを入れ その9マスの各列(タテ、ヨコ、ナナメ)の合計を出し それぞれの合計のうち、最大値と最小値の差がもっとも小さくなる 組み合わせはどれか <数字> 13、16、17、21、25、 28、32、34、39、44、 45、47、53、55、59、 62、64、66、71、75、 79、82、84、87、93、 96、98

  • 複数列の組み合わせがユニークな行数をカウントしたい

    excelで、A列とB列の組み合わせがユニークな行数を数えたいと思っています。 COUNTA(UNIQUE(A2:B200))/2-1 複数列指定した時に返ってくるのが配列で、COUNTIFそのままだと A列とB列の数が合算されて返るようなので2で割り、頭になぜか 0、0がついているので-1として、とりあえずそれらしき値は出せたの ですが、もっとうまいやり方があれば教えていただけないでしょうか。

  • 要素数を最大化する組合せ最適化問題について

    要素数を最大化するような組合せ最適化問題(線形計画問題)を解こうとしていますが、 要素数を一度に計算したり、ソートしたりすることはできません。 (そのような関数を線形式で定義するのは難しいと思いますので。) 一方、2つの要素が同一かどうかのみの計算は簡単にできるので、 全ての2要素間で一致/不一致を判断し、不一致の数が最大となるように目的関数を設定して、この問題を解こうかと思っています。 この方法は正しいでしょうか。 例えば、 ある変数の組合せにおいて、 A1=X, A2=Y, A3=X といった結果になるとすると、 bin1=|A1-A2|(=1、不一致) bin2=|A1-A3|(=0、一致) bin3=|A2-A3|(=1、不一致) という風に要素の一致/不一致を計算し、 不一致数(=bin1+bin2+bin3)を最大化するという風に目的関数を定義しようかと思っています。 当然、不一致数と要素数は一致しないわけですが、 不一致数が最大のときに、必ず要素数が最大となるのであれば、 目的関数として問題ないと考えています。 なんとなく正しい気もしますが、本当に正しいのかよくわかりません。 よろしくお願いします。

専門家に質問してみよう