###前提・実現したいこと
プログラミング言語C++でk*kのある配列を作ろうとしています。
まずkの要素は4つでそれぞれ1~12の値が入ります。kの4つの要素をそれぞれabcdとして
以下のような配列を作っています。そして0より値が小さくなった場合0と12を基準に巡回しています。例えば-2の場合9、-1の場合12です。
(a-a), a-b , a-c, a-d
b-a ,(b-b), b-c, b-d
c-a , c-b, (c-c), c-d
d-a , d-b , d-c, (d-d)
そして、この配列が対角線上になる0 ”()”で括っている部分を除く数が1回だけ出現しているか検査するプログラムをつくっています。
###発生している問題・エラーメッセージ
莫大な量の計算なので効率化を図りたいので、kの4つの要素が例えば(1,2,3,4)の時と
(1,2,4,3)や(2,1,4,3)の時などの重複配列は一緒なので配列を作る前に省きたいのですが、どのように省けばよいでしょうか?以下のプログラムコードを貼りますので改良のほうお願いします。
###該当のソースコード
C++
1#include <iostream> 2 3using namespace std; 4 5/** 6引数の配列をきれいに表示するやつ 7int* a -> 配列データの先頭アドレス 8int size -> 配列の大きさ 9*/ 10void drawSgArray(int* a, int size) { 11 for (int i = 0; i < size; i++) { 12 if (a[i] < 10) { cout << " " << a[i]; } 13 else { cout << a[i]; } 14 if (i < size - 1) cout << ","; 15 } 16 17 return; 18} 19 20/** 21引数の2次元配列をきれいに表示するやつ 22int** a -> 二次元配列データの先頭アドレス 23int low -> 行の大きさ 24int col -> 列の大きさ 25*/ 26void drawDwArray(int** a, int row, int col) { 27 for (int i = 0; i < col; i++) { 28 for (int j = 0; j < row; j++) { 29 if (a[i][j] < 10) { cout << " " << a[i][j]; } 30 else { cout << a[i][j]; } 31 if (j < row - 1) cout << ","; 32 } 33 cout << endl; 34 } 35 36 return; 37} 38 39/** 40巡回差行列になっているか。なっていたらtrueを返す。 41int** a -> 二次元配列の先頭アドレス 42int size -> 配列の長さ 43int max -> 最大値 44int imp -> 各値の表示回数 45*/ 46bool check(int** a, int size, int max, int imp) { 47 int* checker = new int[max + 1]; // 各値の表示回数を数えるやつ 48 49 // checkerの初期化 50 for (int i = 0; i < max + 1; i++) checker[i] = 0; 51 52 // 行列の各要素の値を見て、どの値が何回出ているのかをcheckerに記録 53 for (int i = 0; i < size; i++) { 54 for (int j = 0; j < size; j++) { 55 if (i != j) checker[a[i][j]]++; 56 } 57 } 58 59 // 数字の出る回数がおかしかったらfalse 60 for (int k = 1; k < max; k++) { 61 if (checker[k] != imp) return false; 62 } 63 64 // 何事もなかったらtrue 65 return true; 66} 67 68int main() { 69 // ============================================================================================ 70 // 初期設定 71 int cnt=0; //カウント 72 int matrixSize; // 行列の大きさ 73 int numberMax; // 最大値 74 int impression; // 出現回数 75 int isAll; // デバッグ 76 77 cout << "配列の大きさ:"; 78 cin >> matrixSize; 79 80 cout << "最大値:"; 81 cin >> numberMax; 82 83 cout << "出現回数:"; 84 cin >> impression; 85 86 cout << "すべての配列を出力する?(YES=1 / NO=0):"; 87 cin >> isAll; 88 89 // ============================================================================================ 90 // 間違い検知 91 if ((matrixSize * (matrixSize - 1)) % (numberMax - 1) != 0 || matrixSize <= 1) { 92 cout << "numberMaxの値、もしくはmatrixSizeの値を間違えて入力しています。" << endl; 93 cin.get(); 94 cin.get(); 95 return 0; 96 } 97 // ============================================================================================ 98 // 計測開始 99 int number[99] = {}; // 行列に代入する値を入れておく配列 100 for (;;) { 101 // 行列を表す二次元配列(matrix)の準備 102 int** matrix = new int*[matrixSize]; 103 for (int i = 0; i < matrixSize; i++) { 104 matrix[i] = new int[matrixSize]; 105 } 106 107 // 行列に値を代入 108 for (int i = 0; i < matrixSize; i++) { 109 for (int j = 0; j < matrixSize; j++) { 110 matrix[i][j] = number[i] - number[j]; 111 if (matrix[i][j] < 0) matrix[i][j] += numberMax; 112 } 113 } 114 115 116 // ============================================================================================ 117 // 巡回差行列になっているかのチェック 118 if (check(matrix, matrixSize, numberMax, impression) || isAll) { 119 // もしも巡回差行列になっていたらコンソールに表示(isAllが1なら無理やり表示) 120 cout << "========================" << endl; 121 cnt++; 122 // 代入した値をとりあえず書き出す 123 cout << "("; 124 drawSgArray(number, matrixSize); 125 cout << ")" << endl; 126 127 // 行列を書き出す 128 drawDwArray(matrix, matrixSize, matrixSize); 129 130 } 131 132 // ============================================================================================ 133 // 次の数字へ(2,3,0,1なら、3,3,0,1になる) 134 number[0]++; 135 for (int i = 0; i < matrixSize - 1; i++) { 136 if (number[i] >= numberMax) number[i + 1]++; 137 } 138 for (int i = 0; i < matrixSize - 1; i++) { 139 // 繰り上げが必要ならやっておく 140 if (number[i] >= numberMax) number[i] %= numberMax; 141 } 142 143 // ============================================================================================ 144 // メモリの開放 145 for (int i = 0; i < matrixSize; ++i) delete matrix[i]; 146 delete matrix; 147 148 // ============================================================================================ 149 // 最後まで計測できたのなら止める 150 if (number[matrixSize - 1] >= numberMax) break; 151 } 152 153 cin.get(); 154 cout<<"巡回差集合は"<<cnt/24<<"個あります。"<<endl; 155 cin.get(); 156 157 return 0; 158}
###試したこと
メモ化も試してみたのですが12121212個も配列を作ることが出来なかったので無理でした・・・
###補足情報(言語/FW/ツール等のバージョンなど)
統合開発環境はVisual studio 2012です
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/12/01 01:59