Problem:
失われし数

時は3xxx年、高度に発達した文明は停滞期を迎えていた。歴史家たちはこの状況を打開しようと過去の叡智を学ぶことにした。注目したのはコンピュータ創世期の天才が残した資料である。この資料には計算式が書かれておりその計算結果が知りたいのだが、残念ながらその一部の文字が薄れて読めなくなっている。仕方がないので計算結果としてありえる最も大きい数を求めることにした。

計算式は2進数で書かれており、演算は足し算・引き算・掛け算の3種類である。括弧も用いられているが括弧内が数字のみであることはない。正確には以下のBNFで定義された文法を満たしている必要がある。

<expression> ::= <number> | <expression> <operation> <expression>
| ( <expression> <operation> <expression> )
<number> ::= <digit> | <number> <digit>
<operation> ::= + | - | *
<digit> ::= 0 | 1

当時のコンピュータの計算能力の限界により、数字は0以上210未満の整数であり計算中もこの範囲を出ることはない。ただし計算は括弧内を先に行い、掛け算は足し算・引き算より先に行う。それ以外の場合は左から順に計算する。

Input

入力は1行からなり、解読すべき数式が1つ与えられる。数式は1文字以上100文字以下である。1つの数式について最大5文字が読めなくなっていて、「.」で表現されている。与えられる数式に含まれる文字は01+-*().のいずれかである。

Constraints

数式は1文字以上100文字以下

改行を除くすべての文字は01+-*().のいずれか

.の個数は5個以下

Output

元の数式として考えられるものの内、計算結果が最大となるものを求め、計算結果を10進法で出力せよ。読めなくなっている文字をどのように埋めても元の数式と考えられるものを作れないときは-1を出力せよ。

Sample Input 1

000

Output for the Sample Input 1

0

Sample Input 2

0.0

Output for the Sample Input 2

2

Sample Input 3

...

Output for the Sample Input 3

7

Sample Input 4

(1.1)

Output for the Sample Input 4

2

Sample Input 5

0-1.

Output for the Sample Input 5

-1

Solution in JAVA (judge verdict: Accepted)

import java.util.*;
import java.lang.*;
import java.math.*;
import java.io.*;
import static java.lang.Math.*;
import static java.util.Arrays.*;
import static java.util.Collections.*;

public class Main{
	Scanner sc=new Scanner(System.in);

	int INF=1<<28;
	double EPS=1e-12;

	String s;

	void run(){
		s=sc.nextLine();
		solve();
	}

	char[] cs;
	int max;

	void solve(){
		s+="$";
		cs=s.toCharArray();
		max=-1;
		dfs(0);
		println(max+"");
	}

	void dfs(int i){
		char[] op={'0', '1', '+', '-', '*', '(', ')'};
		if(i==cs.length){
			// 発動
			max=max(max, calc());
			return;
		}
		if(cs[i]=='.'){
			for(char c : op){
				cs[i]=c;
				dfs(i+1);
				cs[i]='.';
			}
		}else{
			dfs(i+1);
		}
	}

	int calc(){
		Result r=E(0);
		// debug(cs);
		r.good&=r.p==cs.length-1;
		// debug(r.good, r.p, r.value);
		// ()の間には記号がいる
		// if(false)
		if(r.good){
			// ((1*1)) X
			int n=cs.length;
			for(int i=0; i<n; i++){
				if(cs[i]!='('){
					continue;
				}
				int left=i, right=left+1;
				int stack=0;
				boolean op=false;
				for(; cs[right]!=')'||stack!=0; right++){
					if(cs[right]=='('){
						stack++;
					}else if(cs[right]==')'){
						stack--;
					}
					if(stack==0)
					op|=cs[right]=='+'||cs[right]=='-'||cs[right]=='*';
				}
				// debug(left, right);
				if(false){
				for(left++; cs[left]!='('&&cs[left]!=')'; left++){
					op|=cs[left]=='+'||cs[left]=='-'||cs[left]=='*';
				}
				for(right--; cs[right]!='('&&cs[right]!=')'; right--){
					op|=cs[right]=='+'||cs[right]=='-'||cs[right]=='*';
				}
				}
				// debug("op", op);
				r.good&=op;
			}
			// debug(r.bad);
		}
		/*
		if(r.good&&new String(cs).indexOf('(')>=0){
			debug(new String(cs), r.value);
		}
		*/
		return r.good?r.value:-1;
	}

	// 0~1023

	boolean debug=false;

	Result E(int p){
		if(debug)
			debug("E", p);
		Result r=F(p);
		if(!r.good){
			return r;
		}
		for(; cs[r.p]=='+'||cs[r.p]=='-';){
			Result r2=F(r.p+1);
			if(!r2.good){
				return r2;
			}
			if(cs[r.p]=='+'){
				r.value+=r2.value;
			}else{
				r.value-=r2.value;
			}
			r.update();
			if(!r.good){
				return r;
			}
			r.p=r2.p;
		}
		return r;
	}

	Result F(int p){
		if(debug)
			debug("F", p);
		Result r=T(p);
		if(!r.good){
			return r;
		}
		for(; cs[r.p]=='*';){
			Result r2=T(r.p+1);
			if(!r2.good){
				return r2;
			}
			r.value*=r2.value;
			r.update();
			if(!r.good){
				return r;
			}
			r.p=r2.p;
		}
		return r;
	}

	Result T(int p){
		if(debug)
			debug("T", p);
		if(cs[p]=='('){
			Result r=E(p+1);
			if(!r.good||cs[r.p]!=')'){
				r.good=false;
				return r;
			}
			r.p++;
			return r;
		}else if(cs[p]=='0'||cs[p]=='1'){
			Result r=new Result(p, 0);
			for(; Character.isDigit(cs[r.p]); r.p++){
				r.value=r.value*2+cs[r.p]-'0';
				r.update();
			}
			return r;
		}else{
			return new Result(0, -1);
		}
	}

	class Result{
		int p, value;
		boolean good;

		Result(int p, int value){
			this.p=p;
			this.value=value;
			good=true;
			update();
		}

		void update(){
			if(value<0||value>=1024){
				good=false;
			}
		}
	}

	void debug(Object... os){
		System.err.println(Arrays.deepToString(os));
	}

	void print(String s){
		System.out.print(s);
	}

	void println(String s){
		System.out.println(s);
	}

	public static void main(String[] args){
		new Main().run();
	}
}