AOJ 2255 6/2(1+2)
問題ページ
6/2(1+2) | Aizu Online Judge
解法
構文解析をする。取りうる数字が一意には定まらないので候補全部をsetで持っておき、next_permutationで全通りを試す。括弧ごとに演算子と数字を全部列挙したあと、演算子の取りうる順番を全通り試してその括弧が取りうる数字を求める。
O(n^2n!)でテストケース厳しいとだめそうだけど通ったからセーフ(は?)
#define __USE_MINGW_ANSI_STDIO 0 #include <bits/stdc++.h> using namespace std; typedef long long ll; #define int ll typedef vector<int> VI; typedef vector<VI> VVI; typedef vector<ll> VL; typedef vector<VL> VVL; typedef pair<int, int> PII; #define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i) #define REP(i, n) FOR(i, 0, n) #define ALL(x) x.begin(), x.end() #define IN(a, b, x) (a<=x&&x<b) #define MP make_pair #define PB push_back #ifdef int const ll INF = (1LL<<60); #else const int INF = (1LL<<30); #endif const double PI = 3.14159265359; const double EPS = 1e-12; const int MOD = 1000000007; template <typename T> T &chmin(T &a, const T &b) { return a = min(a, b); } template <typename T> T &chmax(T &a, const T &b) { return a = max(a, b); } template<class S,class T> ostream &operator <<(ostream& out,const pair<S,T>& a){ out<<'('<<a.first<<','<<a.second<<')'; return out; } int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0}; string s; typedef string::const_iterator State; set<int> factor(State& begin); set<int> digit(State& begin); set<int> expr(State& begin) { vector<char> op; vector<set<int>> num; while(begin != s.end() && *begin != ')') { if(*begin == '+') { op.PB('+'); begin++; } else if(*begin == '-') { op.PB('-'); begin++; } else if(*begin == '*') { op.PB('*'); begin++; } else if(*begin == '/') { op.PB('/'); begin++; } else if(*begin == '(') { num.PB(factor(begin)); } else { num.PB(digit(begin)); } } set<int> ret; VI per(op.size()); REP(i, op.size()) per[i] = i; do { VI p(per); for(int i=per.size()-1; i>=0; --i) { int tmp = 0; REP(j, i) { if(p[j] < p[i]) tmp++; } p[i] -= tmp; } vector<set<int>> num2(num); REP(i, per.size()) { // p[i] と p[i]+1についての演算をする if(op[per[i]] == '+') { set<int> tmp; for(int j: num2[p[i]]) for(int k: num2[p[i]+1]) { tmp.insert(j+k); } num2[p[i]] = tmp; num2.erase(num2.begin()+p[i]+1); } else if(op[per[i]] == '-') { set<int> tmp; for(int j: num2[p[i]]) for(int k: num2[p[i]+1]) { tmp.insert(j-k); } num2[p[i]] = tmp; num2.erase(num2.begin()+p[i]+1); } else if(op[per[i]] == '*') { set<int> tmp; for(int j: num2[p[i]]) for(int k: num2[p[i]+1]) { tmp.insert(j*k); } num2[p[i]] = tmp; num2.erase(num2.begin()+p[i]+1); } else if(op[per[i]] == '/') { set<int> tmp; for(int j: num2[p[i]]) for(int k: num2[p[i]+1]) { if(k == 0) continue; tmp.insert(j/k); } num2[p[i]] = tmp; num2.erase(num2.begin()+p[i]+1); } } for(int i: num2[0]) ret.insert(i); } while(next_permutation(ALL(per))); return ret; } set<int> factor(State& begin) { begin++; set<int> ret = expr(begin); begin++; return ret; } set<int> digit(State& begin) { int ret = 0; while(isdigit(*begin)) { ret *= 10; ret += *begin - '0'; begin++; } return {ret}; } signed main(void) { while(true) { cin >> s; if(s == "#") break; State begin = s.begin(); set<int> ret = expr(begin); cout << ret.size() << endl; } return 0; }