poj--1100 Dreisam Equations(dfs)

来源:互联网 发布:上帝悖论 知乎 编辑:程序博客网 时间:2024/06/05 12:46

Problem Link

题解

在等式中重新放置 + - * 以便构造一个有效的等式。

对于每个可以放置运算符的位置,都有三种选择,因此解空间是一棵完全三叉树,回溯搜索O(3n)

需要注意存在冗余括号的情况。

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cctype>using namespace std;#define LEFT  -1    // 左括号#define RIGHT -2    // 右括号#define MUL   -3    // *#define ADD   -4    // +#define SUB   -5    // -#define OP    -6    // 有运算符#define NONE  -10const int maxn = 100;char a[maxn];   // 原始的等式数据int b[maxn];    // 伪表达式int best[maxn]; // 存储答案int op[maxn];   // 运算符在数组b中的位置int bn;         // 数组b的项数int iLeft;      // 等号左边的数int possible;   // 是否有解int apos, bpos, opos;   // 位置指针// 跳过空格void skipSpace(){    while(a[apos] && a[apos] == ' ') apos++;}int compute(); //前向声明,间接递归int bracket(){    int sum;    if(b[bpos] == LEFT){        bpos++; // 跳过左括号        sum = compute();    // 计算括号里面的值        bpos++; // 跳过右括号    }else sum = b[bpos++];    // 没有括号    return sum;}int compute(){    int sum = bracket();    // 右边第一个数    while(b[bpos] == MUL || b[bpos] == ADD || b[bpos] == SUB){        int operation = b[bpos++];     // 取出运算符        int ret = bracket();    // 取下一个数        switch(operation){            case MUL: sum *= ret; break;            case ADD: sum += ret; break;            case SUB: sum -= ret; break;        }    }    return sum;}void dfs(int dep){    if(possible) return;    // 所有的运算符构造完毕,判断等式是否成立    if(dep == opos){        bpos = 0;        int iRight = compute();        if(iRight == iLeft){            possible = 1;            for(int i = 0; i < bn; ++i) best[i] = b[i];        }        return;    }    // Hint: 这里有顺序要求    b[op[dep]] = ADD; dfs(dep + 1);    b[op[dep]] = SUB; dfs(dep + 1);    b[op[dep]] = MUL; dfs(dep + 1);}int main(){#ifndef ONLINE_JUDGEfreopen("data.in", "r", stdin);#endif // ONLINE_JUDGE    int _ = 1;    while(gets(a) && strchr(a, '=')){        possible = 0;        for(int i = 0; i < maxn; ++i) b[i] = NONE;        apos = 0;        sscanf(a, "%d", &iLeft);    // '='左边的数        while(a[apos] && isdigit(a[apos])) apos++;        skipSpace();        apos++; //跳过 '='        // 处理'='右边        bn = 0;        opos = 0;        while(skipSpace(), a[apos]){            if(a[apos] == '('){ // 左括号                b[bn++] = LEFT;                apos++;                continue;            }            if(a[apos] == ')'){ // 右括号                b[bn++] = RIGHT;                apos++;            }else{                sscanf(a + apos, "%d", &b[bn++]);   // 读取数字                while(a[apos] && isdigit(a[apos])) apos++;            }            skipSpace();            // 如果不是结尾和')',则有一个运算符            if(a[apos] && a[apos] != ')'){                op[opos++] = bn;                b[bn++] = OP;            }        }        dfs(0);        printf("Equation #%d:\n", _++);        if(!possible || !bn){            printf("Impossible\n");        }else if(bn == 1 && iLeft == b[0]){            printf("%d=%d\n", iLeft, iLeft);        }else{            printf("%d=", iLeft);            for(int i = 0; i < bn; ++i){                switch(best[i]){                    case ADD:   printf("+"); break;                    case SUB:   printf("-"); break;                    case MUL:   printf("*"); break;                    case LEFT:  printf("("); break;                    case RIGHT: printf(")"); break;                    default :   printf("%d", b[i]); break;                }            }            printf("\n");        }        printf("\n");    }    return 0;}
0 0
原创粉丝点击