2012年1月4日水曜日

重複組み合わせの全件出力プログラム

k_1+k_2+・・・+k_K=N、k_i>=0 を全件表示するプログラムです。
プログラム中のkとnは実際コンストラクタ等で与えておきます。
kが変化すると呼び出すfor文の回数も変わるので再起処理しています。



public class Duplication {

static int idx = 0;

/**
* @param args
*/
public static void main(String[] args) {
// TODO 自動生成されたメソッド・スタブ

int k = 5, n = 10; //実際はコンストラクタで初期化
int k_sum = 0, roop = 0;
long h = (fact(k+n-1)/(fact(n)*fact(k-1)));
int[][] combi = new int[(int)h][k]; //結果を格納のする配列(最終結果)
int[] k_mem = new int[k]; //各ループで上書き

System.out.println("今回はK="+k+", N="+n+"で"+k+"H"+n+"="+(k+n-1)+"C"+n+"となり"+(fact(k+n-1)/(fact(n)*fact(k-1)))+"通りあります");

dupricate(k_mem, k_sum, k, n, roop, combi);

int l = 0;
for (int[] array : combi) {
l++;
    System.out.print("["+l+"]");
    for (int element : array) {
        System.out.print(element);
    }
    System.out.println("");
   
}
}

static long fact(long num){
long i;
if(num == 1){
return 1;
} else {
i = num * fact(num - 1);
return i;
}
}

/**
* @param k_mem[] 各ループのk_iの値
* @param k_sum 今までのk_memの総和
* @param k 拠点数(定数)
* @param n 総台数(定数)
* @param roop 何回目の呼出か(最大K)
* @param combi 結果を格納
* @param idx combiの行番号0~h-1(クラス変数)
*/
static void dupricate(int k_mem[], int k_sum, int k, int n, int roop, int combi[][]){
roop ++; //呼び出された回数をアップ
for( int i = 0; i + k_sum <= n; i++){
k_mem[roop-1] = i; //k_memの要素にiを代入
k_sum += i; //k_sumにiを加える
if(roop == k){ //ループ回数がkに達した場合
if(k_sum == n){ //組み合わせが一致した場合
System.arraycopy(k_mem, 0, combi[idx], 0, k); //一致したらk_memをcombiにコピー
//void java.lang.System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
//System.out.println("COPY");
idx ++;
}
}else {
dupricate(k_mem, k_sum, k, n, roop, combi);
}
k_sum -= i; //今回行った和を戻す
}
}

}

0 件のコメント:

コメントを投稿