#include #include // recursive display tools int indent = 0; ofstream devnull("/dev/null"); ostream& onull = devnull; bool showing = false; /////////////////////////////////////////////////////////// /////// memo table tools ////////////////////////////////// struct State { int s; int TD8; int TD7; int TD6; bool canFG; State(int S=0, int a=0, int b=0, int c=0, int d=false) : s(S), TD8(a), TD7(b), TD6(c), canFG(d) {}; }; bool operator<(const State& a, const State& b) { if (a.s != b.s) return a.s < b.s; if (a.TD8 != b.TD8) return a.TD8 < b.TD8; if (a.TD7 != b.TD7) return a.TD7 < b.TD7; if (a.TD6 != b.TD6) return a.TD6 < b.TD6; return (!a.canFG && b.canFG); } map Memo; /////////////////////////////////////////////////////////// /* scoreways() returns the number of ways to get a score of S while * using 8 point TDs only if TD8 > 0, * using 7pt TDs only if TD7 > 0, * using 6 point TDs only if TD6 > 0, * and using 3pt FGs only if canFG. * Always at most one of TD8, TD7, TD6 is nonzero. */ int scoreways(int s, int TD8, int TD7, int TD6, bool canFG) { int x; State S(s, TD8, TD7, TD6, canFG); map::iterator ways_ptr = Memo.find(S); if (ways_ptr != Memo.end()) return ways_ptr->second; ostream& debug = showing ? cerr : onull; for (int i = 0; i < indent; ++i) debug <<" "; debug << "scoreways(" << s << ", " << TD8 << ", "; debug << TD7 << ", " << TD6 << ", " << canFG <<")\n"; indent +=2; if (s < 0) x = 0; else if (s == 0) x = 1; else if (TD8 > 0) // Compute ways with one or more 8pt TD plus ways with no 8 pt TDs. { x = scoreways( s-8, TD8-1, 0, 0, canFG) + scoreways( s, 0, TD8, 0, canFG); } else if (TD7 > 0) // Compute ways with one or more 7pt TD plus ways with no 7 pt TDs. { x = scoreways( s-7, 0, TD7-1, 0, canFG) + scoreways( s, 0, 0, TD7, canFG); } else if (TD6 > 0) // Compute ways with one or more 6pt TD plus ways with no TDs. { x = scoreways( s-6, 0, 0, TD6-1, canFG) + scoreways( s, 0, 0, 0, canFG); } else if (s >= 3 && canFG) // Compute ways with one or more 3pt FG plus ways with no FGs. { x = scoreways( s-3, 0, 0, 0, true) + scoreways( s, 0, 0, 0, false); } // Compute ways with only safeties. else x = (0 == s%2) ? 1 : 0; indent -=2; for (int i = 0; i < indent; ++i) debug <<" "; debug << x << endl; Memo[S] = x; return x; } main(int argc, char* argv[]) { if (argc > 2) showing = true; int s, t, f; if (argc > 1) { s = atoi(argv[1]); cout << scoreways(s, s/6, 0, 0, true) << endl; cout << "Size of memo table: " << Memo.size() << endl; } else while (cin >> s >> t >> f) { int ans; int TDlimit = (t < 0) ? s/6 : t; if (f >= 0) { s -= 3*f; ans = scoreways(s, TDlimit, 0, 0, false); } else ans = scoreways(s, TDlimit, 0, 0, true); Memo.clear(); if (ans == 0) cout << "Invalid score" << endl; else cout << ans << endl; } }