//************************************************************************* // 簡易ロト問題を解く(最適解を調べる) by takaken 2005/02 //************************************************************************* #include #include #if 1 // 5個から3個以上 #define R 5 #define H 3 #define MH(n) (5*(n)*(n) - 50*(n) + 126) #else // 3個から2個以上 #define R 3 #define H 2 #define MH(n) (3*(n) - 8) #endif #define BOOL int #define TRUE 1 #define FALSE 0 #define MAX_TABLE 5000 #define MAX_DEPTH 100 #define MAX_N 16 int N, NCR, DEPTH, MAX_HIT; int PTN[MAX_TABLE], HIT[MAX_TABLE]; int SEL[MAX_DEPTH]; int ANS_IDX; int ANS_TBL[MAX_DEPTH]; //************************************************************************* // サブルーチン //************************************************************************* // 全パターン(nCr)を生成する BOOL Combination(int r, int i, int bits) { if (r == R) { if (NCR == MAX_TABLE) return FALSE; PTN[NCR++] = bits; } else { for ( ; i>=1) printf("%d", (bits & bit)? 1: 0); } // ヒット判定関数 BOOL IsHit(int bits) { if (!bits) return FALSE; // 0 bits &= (bits - 1); if (!bits) return FALSE; // 1 #if H == 2 return TRUE; // 2以上 #endif bits &= (bits - 1); if (!bits) return FALSE; // 2 return TRUE; // 3以上 } // ヒットテーブルを戻す void HitOff(int bits) { int i; for (i=0; i>=1) { // 次の位置(下位)と連続しているなら if (group1[i]==0 && group1[i-1]!=1 && ((bits & bit)==bit || (bits & bit)==0)) { group2[i] = 0; // 連続中の印 cnt++; // 連続数カウントアップ } else { group2[i] = cnt;// 連続数を書き込む cnt = 1; // 連続数の初期化 } } group2[i] = cnt; return group2; } // 対称性を考慮したユニークパターンか?(右寄せをユニークとする) BOOL IsUnique(int group[], int bits) { int i, bit, flag; for (i=0,bit=1; i maxhit) { maxhit = hit; bits = temp; } } // 最大ヒット数のパターン(bits)を選択する if (ANS_IDX == MAX_DEPTH) return FALSE; ANS_TBL[ANS_IDX++] = bits; HitOn(bits, &nohit); } while (nohit); // 2個を1個で代用できるか do { update = FALSE; for (a=0; a=0; j--) { bits = PTN[j]; HitOn(bits, &nohit); if (nohit == 0) break; HitOff(bits); } // 成功したので結果を更新する if (j >= 0) { ANS_TBL[a] = bits; for (j=b+1; j%d: N=%d,", R, H, N); // 欲張り法(上限値を求める) for (i=0; i"); if (!Backtrack(0, 0, group, NCR)) break; // 解の記録を更新する ANS_IDX = DEPTH; for (i=0; i