Input
18=7 (5 3) 2
30=3 3 5
18=3 3 5
5=3 3
0
Output
Equatio #1: Equatio #2: Equatio #3: Equatio #4:
18=7+ (5 -3) *2 30=3 +3 *5 Impossible Impossible
#include
#include
#include
#include
//*******************************************
const int left(-1), right(-2); //左右括号
const int mul(-3), add_(-4), sub(-5); //*、+、-号
const int OP(-6); //有运算符
const int none(-10); //无运算符
//*******************************************
char oDate[100]; //原始数据
int fEx[100] = {0}; //伪表达式
int ans[100] = {0}; //答案
int op[30] = {0}; //运算符在b数组中位置
int fExNum(0); //数组b的项数
int iLeft(0); //等式左边的数
int apos(0), bpos(0), opos(0); //数组a、b及操作符数组的位置指针
int possible(0); //是否有解
//*******************************************
void space();//跳过空格
int bracket();//计算括号内
int compute();//计算表达式
void backtrack(int dep);//回溯
void print( int *);//输出
/*******************************************
*main
*/
int main() {
int iCase(0);
while ( gets(oDate) && strchr( oDate, '=' ) ) {
possible = 0;
int i(0);
for ( ; i != 90; ++i ) {
fEx[i] = none; //初值
}
apos = 0;
sscanf(oDate, "%d", &iLeft); //左边的数
while ( oDate[apos] && isdigit(oDate[apos]) ){ //将位置指针移到数字后面
++apos;
}
space();
++apos; //跳过'='
fExNum = 0;
opos = 0;
while ( space(), oDate[apos] ) {
if ( '(' == oDate[apos] ) { //左括号
fEx[fExNum++] = left;
++apos;
continue;
}
if ( ')' == oDate[apos] ) { //右括号
fEx[fExNum++] = right;
++apos;
} else { //读取数字
sscanf( oDate + apos, "%d", &fEx[fExNum++] );
while ( oDate[apos] && isdigit(oDate[apos]) ) {
++apos;
}
}
space();
if ( oDate[apos] && oDate[apos] != ')' ) { //若不是结尾和')',则有一个运算符
op[opos++] = fExNum;
fEx[fExNum++] = OP;
}
}
backtrack(0);
++iCase;
printf("Equation #%d:\n", iCase);
if ( 1 == fExNum && iLeft == fEx[0] ) {
printf("%d=%d\n", iLeft, iLeft);
} else if ( 0 == fExNum || !possible ) {
printf("Impossible\n");
} else {
print(ans);
printf("\n");
}
printf("\n");
}
return 0;
}
void space() {
while ( oDate[apos] && (' ' == oDate[apos]) ) {
++apos;
}
}
int bracket() {
int sum(0);
if ( left == fEx[bpos]) {
++bpos; //跳过左括号
sum = compute(); //计算括号里的值(注意间接递归)
++bpos; //跳过右括号
} else {
sum = fEx[bpos++]; //无括号
}
return sum;
}
int compute() {
int sum = bracket(); //右边第一个数
while ( mul == fEx[bpos] || add_ == fEx[bpos] || sub == fEx[bpos] ) { //计算每一个运算符
int operation(fEx[bpos++]); //取出运算符
int ret(bracket()); //取出下一个数
switch ( operation ) { //根据运算符计算
case mul: sum *= ret; break;
case add_: sum += ret; break;
case sub: sum -= ret; break;
}
}
return sum;
}
void backtrack(int dep) {
if ( possible ) {
return ; //得到答案
}
if ( opos == dep ) { //所有运算符构造完毕,判断等式是否成立
bpos = 0;
int iRight(compute()); //右边表达式的值
if ( iRight == iLeft ) { //若等式成立,构造最优解
possible = 1; //标记为"有解"
int j(0);
for ( ; j != fExNum; ++j ) {
ans[j] = fEx[j];
}
}
return ;
}
//当前结点的三个孩子结点,用+、-、*构造
fEx[op[dep]] = mul; backtrack(dep + 1);
fEx[op[dep]] = add_; backtrack(dep + 1);
fEx[op[dep]] = sub; backtrack(dep + 1);
}
void print( int *p ) {
printf("%d=", iLeft);
int k(0);
for ( ; k != fExNum; ++k ){
switch(p[k]) {
case add_: printf("+"); break;
case mul : printf("*"); break;
case sub : printf("-"); break;
case left: printf("("); break;
case right: printf(")"); break;
case OP : printf("?"); break;
default : printf("%d", p[k]); break;
}
}
}