2010-1109

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

题意:
给定一些量纲,运算符的优先级和左右结合律,以及量纲之间的关系表达式,求一个量纲集合表达式的运算结果。

解法:
1. 解析表达式(主要设计字符串处理,没什么算法可言,主要需要时间和一些处理字符串的经验)
2. 表达式计算(我用的是逆波兰,复杂度为O(n),shi哥和quark的方法都是构表达式树)
3. 量纲集合之间的运算,因为量纲数量不多,于是直接暴力。

总的说来,题目没什么太难的地方,靠的主要是肉,需要比较快速的编程和debug能力。

代码:
{{{
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <cassert>
#include <cctype>
#include <map>
using namespace std;

const int MAXN = 10 + 1;
const int MAXL = 128 + 1;
const int MAXLL = 100010 + 1;

class Unit {
public:
    bool type;
    vector <int> cnt;
    int idx, p;
    bool lass;

    Unit() {}

    inline void print() {
        printf("type = %d", type);
        if (type) {
            printf(" (");
            for (int i = 0; i < (int)cnt.size(); i++) {
                printf("%d ", cnt[i]);
            }
            putchar(')');
            putchar('\n');
        } else {
            printf(" idx = %d p = %d lass = %d\n", idx, p, lass);
        }
    }
};

int ntype, nop, neq, nexpr, MOD, priority[MAXN], pos;
bool lass[MAXN];
map <string, int> typeMap, opMap;
map < pair <int, int>, int > eqMap[MAXN];
char line[MAXLL];
vector <Unit> rev, opList;

inline void skipSpace() {
    while (isspace(line[pos])) {
        pos++;
    }
}

inline bool isABC123(char ch) {
    return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ('0' <= ch && ch <= '9');
}

inline bool isPunc(char ch) {
    return !isspace(ch) && ch != '\0' && ch != ' ' && ch != '(' && ch != ')' && ch != '\\' && !isABC123(ch);
}

inline string getType() {
    skipSpace();
    char tmpstr[MAXL];
    int len = 0;
    while (isABC123(line[pos])) {
        tmpstr[len++] = line[pos++];
    }
    tmpstr[len] = '\0';
    return tmpstr;
}

inline string getOp() {
    skipSpace();
    if (line[pos] == '(') {
        pos++;
        return "(";
    } else if (line[pos] == ')') {
        pos++;
        return ")";
    } else if (line[pos] == '\\') {
        pos++;
        return "\\";
    }
    char tmpstr[MAXL];
    int len = 0;
    while (isPunc(line[pos])) {
        tmpstr[len++] = line[pos++];
    }
    tmpstr[len] = '\0';
    return tmpstr;
}

int main() {
    while (scanf("%d%d%d%d%d", &ntype, &nop, &neq, &nexpr, &MOD) != EOF) {
        typeMap.clear();
        for (int i = 0; i < ntype; i++) {
            char tmpstr[MAXL];
            scanf("%s", tmpstr);
            typeMap[tmpstr] = i;
        }
        opMap.clear();
        for (int i = 0; i < nop; i++) {
            eqMap[i].clear();
            char tmpstr[MAXL];
            scanf("%s", tmpstr);
            opMap[tmpstr] = i;
            scanf("%d%s", &priority[i], tmpstr);
            lass[i] = tmpstr[0] == 'l';
        }
        gets(line);
        for (int i = 0; i < neq; i++) {
            gets(line);
            pos = 0;
            int x, y, z, op;
            z = typeMap[getType()];
            getOp();
            x = typeMap[getType()];
            op = opMap[getOp()];
            y = typeMap[getType()];
            eqMap[op][make_pair(x, y)] = z;
        }
        for (int o = 0; o < nexpr; o++) {
            gets(line);
            pos = 0;
            rev.clear();
            opList.clear();
            while (true) {
                bool type = true;
                string str = getType();
                if (str.empty()) {
                    type = false;
                    str = getOp();
                    if (str.empty()) break;
                }
                Unit unit;
                unit.type = type;
                if (type) {
                    unit.cnt = vector <int> (ntype);
                    unit.cnt[typeMap[str]] = 1;
                    rev.push_back(unit);
                } else {
                    if (str[0] == ')') {
                        while (!opList.empty() && opList.back().p != -1) {
                            rev.push_back(opList.back());
                            opList.pop_back();
                        }
                        opList.pop_back();
                    } else if (str[0] == '(') {
                        unit.idx = nop;
                        unit.p = -1;
                        opList.push_back(unit);
                    } else {
                        if (str[0] == '\\') {
                            unit.idx = -1;
                            unit.p = 0;
                            unit.lass = true;
                        } else {
                            unit.idx = opMap[str];
                            unit.p = priority[unit.idx];
                            unit.lass = lass[unit.idx];
                        }
                        while (!opList.empty() && opList.back().p < unit.p && opList.back().p != -1) {
                            rev.push_back(opList.back());
                            opList.pop_back();
                        }
                        if (unit.lass) {
                            while (!opList.empty() && opList.back().p == unit.p) {
                                rev.push_back(opList.back());
                                opList.pop_back();
                            }
                        }
                        opList.push_back(unit);
                    }
                }
            }
            while (!opList.empty()) {
                rev.push_back(opList.back());
                opList.pop_back();
            }
            opList.clear();
            for (int i = 0; i < (int)rev.size(); i++) {
                if (rev[i].type) {
                    opList.push_back(rev[i]);
                } else {
                    Unit unit2 = opList.back();
                    opList.pop_back();
                    if (opList.empty()) assert(false);
                    Unit unit, unit1 = opList.back();
                    unit.type = true;
                    unit.cnt = vector <int> (ntype, 0);
                    opList.pop_back();
                    if (rev[i].p == 0) {
                        for (int j = 0; j < ntype; j++) {
                            unit.cnt[j] = (unit1.cnt[j] + unit2.cnt[j]) % MOD;
                        }
                    } else {
                        for (int k = 0; k < ntype; k++) {
                            for (int j = 0; j < ntype; j++) {
                                if (eqMap[rev[i].idx].count(make_pair(k, j))) {
                                    unit.cnt[eqMap[rev[i].idx][make_pair(k, j)]] = (unit.cnt[eqMap[rev[i].idx][make_pair(k, j)]] + (long long)unit1.cnt[k] * unit2.cnt[j]) % MOD;
                                }
                            }
                        }
                    }
                    opList.push_back(unit);
                }
            }
            printf("#%d:\n", o + 1);
            for (int i = 0; i < ntype; i++) {
                for (map <string, int>::iterator iter = typeMap.begin(); iter != typeMap.end(); iter++) {
                    if (iter->second == i) {
                        printf("%s: %d\n", iter->first.c_str(), opList.back().cnt[i]);
                        break;
                    }
                }
            }
        }
        putchar('\n');
    }
    return 0;
}
}}}

题意:

给定一些量纲,运算符的优先级和左右结合律,以及量纲之间的关系表达式,求一个量纲集合表达式的运算结果。

解法:

1. 解析表达式(主要设计字符串处理,没什么算法可言,主要需要时间和一些处理字符串的经验)

2. 表达式计算(我用的是逆波兰,复杂度为O(n),shi哥和quark的方法都是构表达式树)

3. 量纲集合之间的运算,因为量纲数量不多,于是直接暴力。

总的说来,题目没什么太难的地方,靠的主要是肉,需要比较快速的编程和debug能力。

代码:

#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <cassert>
#include <cctype>
#include <map>
using namespace std;
const int MAXN = 10 + 1;
const int MAXL = 128 + 1;
const int MAXLL = 100010 + 1;
class Unit {
public:
    bool type;
    vector <int> cnt;
    int idx, p;
    bool lass;
    Unit() {}
    inline void print() {
        printf("type = %d", type);
        if (type) {
            printf(" (");
            for (int i = 0; i < (int)cnt.size(); i++) {
                printf("%d ", cnt[i]);
            }
            putchar(')');
            putchar('\n');
        } else {
            printf(" idx = %d p = %d lass = %d\n", idx, p, lass);
        }
    }
};
int ntype, nop, neq, nexpr, MOD, priority[MAXN], pos;
bool lass[MAXN];
map <string, int> typeMap, opMap;
map < pair <int, int>, int > eqMap[MAXN];
char line[MAXLL];
vector <Unit> rev, opList;
inline void skipSpace() {
    while (isspace(line[pos])) {
        pos++;
    }
}
inline bool isABC123(char ch) {
    return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ('0' <= ch && ch <= '9');
}
inline bool isPunc(char ch) {
    return !isspace(ch) && ch != '\0' && ch != ' ' && ch != '(' && ch != ')' && ch != '\\' && !isABC123(ch);
}
inline string getType() {
    skipSpace();
    char tmpstr[MAXL];
    int len = 0;
    while (isABC123(line[pos])) {
        tmpstr[len++] = line[pos++];
    }
    tmpstr[len] = '\0';
    return tmpstr;
}
inline string getOp() {
    skipSpace();
    if (line[pos] == '(') {
        pos++;
        return "(";
    } else if (line[pos] == ')') {
        pos++;
        return ")";
    } else if (line[pos] == '\\') {
        pos++;
        return "\\";
    }
    char tmpstr[MAXL];
    int len = 0;
    while (isPunc(line[pos])) {
        tmpstr[len++] = line[pos++];
    }
    tmpstr[len] = '\0';
    return tmpstr;
}
int main() {
    while (scanf("%d%d%d%d%d", &ntype, &nop, &neq, &nexpr, &MOD) != EOF) {
        typeMap.clear();
        for (int i = 0; i < ntype; i++) {
            char tmpstr[MAXL];
            scanf("%s", tmpstr);
            typeMap[tmpstr] = i;
        }
        opMap.clear();
        for (int i = 0; i < nop; i++) {
            eqMap[i].clear();
            char tmpstr[MAXL];
            scanf("%s", tmpstr);
            opMap[tmpstr] = i;
            scanf("%d%s", &priority[i], tmpstr);
            lass[i] = tmpstr[0] == 'l';
        }
        gets(line);
        for (int i = 0; i < neq; i++) {
            gets(line);
            pos = 0;
            int x, y, z, op;
            z = typeMap[getType()];
            getOp();
            x = typeMap[getType()];
            op = opMap[getOp()];
            y = typeMap[getType()];
            eqMap[op][make_pair(x, y)] = z;
        }
        for (int o = 0; o < nexpr; o++) {
            gets(line);
            pos = 0;
            rev.clear();
            opList.clear();
            while (true) {
                bool type = true;
                string str = getType();
                if (str.empty()) {
                    type = false;
                    str = getOp();
                    if (str.empty()) break;
                }
                Unit unit;
                unit.type = type;
                if (type) {
                    unit.cnt = vector <int> (ntype);
                    unit.cnt[typeMap[str]] = 1;
                    rev.push_back(unit);
                } else {
                    if (str[0] == ')') {
                        while (!opList.empty() && opList.back().p != -1) {
                            rev.push_back(opList.back());
                            opList.pop_back();
                        }
                        opList.pop_back();
                    } else if (str[0] == '(') {
                        unit.idx = nop;
                        unit.p = -1;
                        opList.push_back(unit);
                    } else {
                        if (str[0] == '\\') {
                            unit.idx = -1;
                            unit.p = 0;
                            unit.lass = true;
                        } else {
                            unit.idx = opMap[str];
                            unit.p = priority[unit.idx];
                            unit.lass = lass[unit.idx];
                        }
                        while (!opList.empty() && opList.back().p < unit.p && opList.back().p != -1) {
                            rev.push_back(opList.back());
                            opList.pop_back();
                        }
                        if (unit.lass) {
                            while (!opList.empty() && opList.back().p == unit.p) {
                                rev.push_back(opList.back());
                                opList.pop_back();
                            }
                        }
                        opList.push_back(unit);
                    }
                }
            }
            while (!opList.empty()) {
                rev.push_back(opList.back());
                opList.pop_back();
            }
            opList.clear();
            for (int i = 0; i < (int)rev.size(); i++) {
                if (rev[i].type) {
                    opList.push_back(rev[i]);
                } else {
                    Unit unit2 = opList.back();
                    opList.pop_back();
                    if (opList.empty()) assert(false);
                    Unit unit, unit1 = opList.back();
                    unit.type = true;
                    unit.cnt = vector <int> (ntype, 0);
                    opList.pop_back();
                    if (rev[i].p == 0) {
                        for (int j = 0; j < ntype; j++) {
                            unit.cnt[j] = (unit1.cnt[j] + unit2.cnt[j]) % MOD;
                        }
                    } else {
                        for (int k = 0; k < ntype; k++) {
                            for (int j = 0; j < ntype; j++) {
                                if (eqMap[rev[i].idx].count(make_pair(k, j))) {
                                    unit.cnt[eqMap[rev[i].idx][make_pair(k, j)]] = (unit.cnt[eqMap[rev[i].idx][make_pair(k, j)]] + (long long)unit1.cnt[k] * unit2.cnt[j]) % MOD;
                                }
                            }
                        }
                    }
                    opList.push_back(unit);
                }
            }
            printf("#%d:\n", o + 1);
            for (int i = 0; i < ntype; i++) {
                for (map <string, int>::iterator iter = typeMap.begin(); iter != typeMap.end(); iter++) {
                    if (iter->second == i) {
                        printf("%s: %d\n", iter->first.c_str(), opList.back().cnt[i]);
                        break;
                    }
                }
            }
        }
        putchar('\n');
    }
    return 0;
}