kmjp's blog

競技プログラミング参加記です

yukicoder : No.2069 み世界数式

実装系問題。
https://yukicoder.me/problems/no/2069

問題

数式が与えられる。
ただし、演算子が+か-かもしくは*か/か確定していない。

計算途中ででる値が0以上Mで収まり、かつ数式を評価した値がansであるような演算子の割り当ては存在するか。
するなら1つ例を答えよ。

解法

構文解析しながら、愚直に「その式がある値になるような演算子割り当ての一例」を総当たりして求めて行こう。

int M,A;
string S;
vector<int> E;

vector<string> expression();
vector<string> term();
vector<string> factor();
vector<string> number();
int pos;

vector<string> expression() {
	vector<string> X=term();
	if(pos<E.size()&&E[pos]==10000+'$') {
		pos++;
		vector<string> Y=expression();
		vector<string> Z(M+1);
		
		int x,y;
		FOR(x,M+1) if(X[x].size()) FOR(y,M+1) if(Y[y].size()) {
			if(x+y<=M) {
				Z[x+y]=Y[y]+"+"+X[x];
			}
			if(y-x>=0) {
				Z[y-x]=Y[y]+"-"+X[x];
			}
		}
		return Z;
	}
	else {
		return X;
	}
	
}
vector<string> term() {
	vector<string> X=factor();
	if(pos<E.size()&&E[pos]==10000+'&') {
		pos++;
		vector<string> Y=term();
		vector<string> Z(M+1);
		
		int x,y;
		FOR(x,M+1) if(X[x].size()) FOR(y,M+1) if(Y[y].size()) {
			if(x*y<=M) {
				Z[x*y]=Y[y]+"*"+X[x];
			}
			if(x) Z[y/x]=Y[y]+"/"+X[x];
		}
		return Z;
	}
	else {
		return X;
	}
	
}
vector<string> factor() {
	
	
	if(E[pos]==10000+')') {
		pos++;
		vector<string> R=expression();
		FORR(r,R) if(r.size()) r='('+r+')';
		assert(E[pos]==10000+'(');
		pos++;
		return R;
	}
	else {
		return number();
	}
	
	
}
vector<string> number() {
	vector<string> R(M+1);
	R[E[pos]]=to_string(E[pos]);
	pos++;
	return R;
	
}


void solve() {
	int i,j,k,l,r,x,y; string s;
	
	cin>>M>>A>>S;
	FORR(c,S) {
		if(c>='0'&&c<='9') {
			if(E.empty()||E.back()>=10000) E.push_back(0);
			E.back()=E.back()*10+c-'0';
			if(E.back()>M) {
				cout<<-1<<endl;
				return;
			}
		}
		else {
			E.push_back(10000+c);
		}
	}
	reverse(ALL(E));
	auto R=expression();
	if(R[A].empty()) cout<<-1<<endl;
	else cout<<R[A]<<endl;
}

まとめ

ややこしいし実装は手間だけど、内容は典型的だし難しさはないかもな。