#include <iostream> #include <vector> using namespace std; template <typename T> void PrintVector(vector<T> vec){ cout << "["; for (typename vector<T>::iterator it = vec.begin(); it != vec.end(); it++) { if (it != vec.begin()) cout << ", "; cout << *it; } cout << "]" << endl; } // class : make combination // set numArray that you want to make combination // call Reset() at first // call Next() to make combination of numArray. result is set to comArray // return value of Next() is 0 ==> no more combination // Print() : print comArray (current combination) template <typename T> class Combination { private: vector<int> comParam; public: vector<T> numArray; vector<T> comArray; Combination() {} Combination(vector<T> a) { numArray = a; } int Reset() { int size = numArray.size(); comParam.clear(); for (int i = 0; i < size; i++) { comParam.push_back((i == 0) * size); } comArray = numArray; return 0; } int Next() { int size = comParam.size(); int pos, carry; pos = size - 1; carry = 1; while (carry && (pos >= 0)) { comParam[pos] = comParam[pos] - carry; if (comParam[pos] < 0) { comParam[pos] = size - pos - 1; carry = 1; pos --; } else { carry = 0; } } if (pos < 0) return 0; comArray = numArray; for (int i = 0; i < size; i++) { T tmp = comArray[i]; comArray[i] = comArray[i + comParam[i]]; comArray[i + comParam[i]] = tmp; } return 1; } void Print() { PrintVector<T>(comArray); } }; class BilliardProblem : private Combination<int> { public: vector<int> ballArray; // ball number list int ballNum; // number of ball int ballSum; // sum of all ball ( sum = n * (n - 1) + 1 ) BilliardProblem(int n) { ballNum = n; ballSum = n * (n - 1) + 1; ballArray.clear(); // make initial ball list int sum = 0; for (int i = 1; i <= n - 1; i++) { ballArray.push_back(i); sum += i; } ballArray.push_back(ballSum - sum); } // find next ball list int Next() { int pos; pos = ballNum - 1; if (pos <= 2) return 0; ballArray[pos-1] = ballArray[pos-1] + 1; ballArray[pos] = ballArray[pos] - 1; if (ballArray[pos-1] >= ballArray[pos]) { pos--; while (pos > 2) { ballArray[pos-1] = ballArray[pos-1] + 1; for (int i = pos; i < ballNum - 1; i++) { ballArray[i] = ballArray[i-1] + 1; } int sum = 0; for (int i = 0; i < ballNum - 1; i++) { sum += ballArray[i]; } ballArray[ballNum - 1] = ballSum - sum; if (ballArray[ballNum - 1] > ballArray[ballNum - 2]) { return 1; } else { pos--; } } return 0; } return 1; } // check all combination of ball list int Check() { int nExist = 0; int count = 0; numArray = ballArray; Combination::Reset(); while (Combination::Next()) { // sum check for (int n = 1; n <= ballSum / 2 + 1; n++) { nExist = 0; for (int i = 1; i <= ballNum; i++) { for (int j = 0; j < ballNum; j++) { int sum = 0; for (int k = 0; k < i; k++) { sum += comArray[(j + k) % ballNum]; } if (n == sum) { nExist = 1; break; } } if (nExist == 1) break; } if (nExist == 0) break; } // combination found then print combination if (nExist) { Combination::Print(); count++; } } return count; } // print ball list void Print() { PrintVector<int>(ballArray); } }; int main(void) { BilliardProblem *ballSet; int count; for (int ball = 1; ball <= 7; ball++) { ballSet = new BilliardProblem(ball); cout << "===============================================" << endl; cout << "Check " << ball << " balls."; cout << " ( 1 - " << ballSet->ballSum << " )" << endl; count = 0; do { count += ballSet->Check(); } while (ballSet->Next()); cout << count << " ways found, "; cout << "include combination of mirror and rotation." << endl; cout << "(" << count / ball / ((ball <= 2 ) ? 1 : 2); cout << " ways without mirror and rotation)" << endl; delete ballSet; } return 0; }
Standard input is empty
=============================================== Check 1 balls. ( 1 - 1 ) [1] 1 ways found, include combination of mirror and rotation. (1 ways without mirror and rotation) =============================================== Check 2 balls. ( 1 - 3 ) [2, 1] [1, 2] 2 ways found, include combination of mirror and rotation. (1 ways without mirror and rotation) =============================================== Check 3 balls. ( 1 - 7 ) [4, 1, 2] [4, 2, 1] [2, 4, 1] [2, 1, 4] [1, 4, 2] [1, 2, 4] 6 ways found, include combination of mirror and rotation. (1 ways without mirror and rotation) =============================================== Check 4 balls. ( 1 - 13 ) [7, 1, 3, 2] [7, 2, 3, 1] [3, 1, 7, 2] [3, 2, 7, 1] [2, 7, 1, 3] [2, 3, 1, 7] [1, 7, 2, 3] [1, 3, 2, 7] [6, 4, 1, 2] [6, 2, 1, 4] [4, 6, 2, 1] [4, 1, 2, 6] [2, 6, 4, 1] [2, 1, 4, 6] [1, 4, 6, 2] [1, 2, 6, 4] 16 ways found, include combination of mirror and rotation. (2 ways without mirror and rotation) =============================================== Check 5 balls. ( 1 - 21 ) [10, 3, 1, 5, 2] [10, 2, 5, 1, 3] [5, 1, 3, 10, 2] [5, 2, 10, 3, 1] [3, 10, 2, 5, 1] [3, 1, 5, 2, 10] [2, 10, 3, 1, 5] [2, 5, 1, 3, 10] [1, 5, 2, 10, 3] [1, 3, 10, 2, 5] 10 ways found, include combination of mirror and rotation. (1 ways without mirror and rotation) =============================================== Check 6 balls. ( 1 - 31 ) [14, 1, 7, 3, 2, 4] [14, 4, 2, 3, 7, 1] [7, 1, 14, 4, 2, 3] [7, 3, 2, 4, 14, 1] [4, 14, 1, 7, 3, 2] [4, 2, 3, 7, 1, 14] [3, 7, 1, 14, 4, 2] [3, 2, 4, 14, 1, 7] [2, 4, 14, 1, 7, 3] [2, 3, 7, 1, 14, 4] [1, 14, 4, 2, 3, 7] [1, 7, 3, 2, 4, 14] [14, 1, 3, 6, 2, 5] [14, 5, 2, 6, 3, 1] [6, 3, 1, 14, 5, 2] [6, 2, 5, 14, 1, 3] [5, 14, 1, 3, 6, 2] [5, 2, 6, 3, 1, 14] [3, 6, 2, 5, 14, 1] [3, 1, 14, 5, 2, 6] [2, 6, 3, 1, 14, 5] [2, 5, 14, 1, 3, 6] [1, 14, 5, 2, 6, 3] [1, 3, 6, 2, 5, 14] [10, 1, 3, 2, 7, 8] [10, 8, 7, 2, 3, 1] [8, 10, 1, 3, 2, 7] [8, 7, 2, 3, 1, 10] [7, 8, 10, 1, 3, 2] [7, 2, 3, 1, 10, 8] [3, 1, 10, 8, 7, 2] [3, 2, 7, 8, 10, 1] [2, 7, 8, 10, 1, 3] [2, 3, 1, 10, 8, 7] [1, 10, 8, 7, 2, 3] [1, 3, 2, 7, 8, 10] [13, 1, 2, 5, 4, 6] [13, 6, 4, 5, 2, 1] [6, 13, 1, 2, 5, 4] [6, 4, 5, 2, 1, 13] [5, 4, 6, 13, 1, 2] [5, 2, 1, 13, 6, 4] [4, 6, 13, 1, 2, 5] [4, 5, 2, 1, 13, 6] [2, 5, 4, 6, 13, 1] [2, 1, 13, 6, 4, 5] [1, 13, 6, 4, 5, 2] [1, 2, 5, 4, 6, 13] [12, 5, 1, 2, 7, 4] [12, 4, 7, 2, 1, 5] [7, 4, 12, 5, 1, 2] [7, 2, 1, 5, 12, 4] [5, 12, 4, 7, 2, 1] [5, 1, 2, 7, 4, 12] [4, 12, 5, 1, 2, 7] [4, 7, 2, 1, 5, 12] [2, 7, 4, 12, 5, 1] [2, 1, 5, 12, 4, 7] [1, 5, 12, 4, 7, 2] [1, 2, 7, 4, 12, 5] 60 ways found, include combination of mirror and rotation. (5 ways without mirror and rotation) =============================================== Check 7 balls. ( 1 - 43 ) 0 ways found, include combination of mirror and rotation. (0 ways without mirror and rotation)