ACM-ZOJ 1145 回溯

 
       话说骚扰了一下做ACM的同学,突然发现玩了一天的我想刷题了,于是上分类题库中找了道回溯(因为上次提到了回溯,我还想赚赚人气)看着思路还挺清晰,于是……于是……果断的做了两个多点,我表示真心伤不起呀,现在脑子都成浆糊了。最后改来改去还该出个函数声明错误,犯这种低级错误我也真心无语……AC代码放出:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <ctype.h>

//*******************************************
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};
int  fExNum(0);
int  iLeft(0);
int  apos(0), bpos(0), opos(0);
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;
        }
    }
}

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值