AOJ2680 LR
'L', 'R', '?', '数字', ',' で構成された文字列が与えられる。, であるとき、文字列の出力を最大化せよ。
また、正しい数または式が生成できない場合はinvalidとせよ。
文字列長 <= 50
解答
'?'に数字を埋める場合は全て'9'で埋めれば良い。与えられた文字列の部分文字列]は、必ず数字またはまたはの式である。よって、] = "数", "L...)", "R...)"となるように区間DPすれば良い。再帰の基底は部分文字列が数となる場合で、部分文字列のすべての文字が'?'または'数字'である場合である。
string const invalid = string(1, '0'-10); struct number { string s; number() {}; number(string const& s): s(s) {}; bool operator < (number const& r) const { if (s.size() != r.s.size()) return s.size() < r.s.size(); return s < r.s; } bool operator == (const number &x) const { return s == x.s; } }; ostream& operator << (ostream& ost, number const& r) { return ost << r.s; } string s; number dp[55][55]; string nine(string s) { const int n = s.size(); rep(i, n) if(s[i] == '?') s[i] = '9'; if(n > 1 && s[0] == '0') return invalid; return s; } #define srange s.begin()+l, s.begin()+r number solve(int l, int r) { auto& ret = dp[l][r]; if(!ret.s.empty()) return ret; ret = invalid; bool dcheck = 1; REP(i, l, r) dcheck &= isdigit(s[i]) || s[i] == '?'; if(dcheck) return ret = nine(string(srange)); if((s[l] == 'L' || s[l] == 'R' || s[l] == '?') && (s[l + 1] == '(' || s[l + 1] == '?') && (s[r - 1] == ')' || s[r - 1] == '?')) { REP(i, l + 3, r - 2) { if(s[i] != '?' && s[i] != ',') continue; auto L = solve(l + 2, i); auto R = solve(i + 1, r - 1); if(L == invalid) continue; if(R == invalid) continue; if(s[l] == 'L' || s[l] == '?') ret = max(ret, L); if(s[l] == 'R' || s[l] == '?') ret = max(ret, R); } } return ret; } int main() { cin >> s; auto r = solve(0, s.size()); if(r == invalid) cout << "invalid\n"; else cout << r << endl; return 0; }