ICPC国内予選C

模擬国内予選と国内予選の参加記も書くつもりですが、取り急ぎCのソースだけ!
Cは一見楽勝に見えてそのまま書き始めると実にかったるい(next_permutationを使ってしまったり)ですが、問題文を読み込めばDFSですっきり書けます。

#include <iostream>
#include <set>
#include <vector>

using namespace std;

int value[10];
bool used[10];
bool not_zero[10];

inline int Eval(const vector<int>& word) {
  int ret = 0;
  for (int i = 0; i < word.size(); ++i)
    ret = ret * 10 + value[word[i]];
  return ret;
}

int Dfs(int depth, int alphabet_size, const vector<vector<int> >& words) {
  if (depth == alphabet_size) {
    int left = 0;
    for (int i = 0; i < words.size() - 1; ++i)
      left += Eval(words[i]);
    int right = Eval(words.back());
    return left == right;
  } else {
    int ret = 0;
    for (int i = not_zero[depth] ? 1 : 0; i < 10; ++i) {
      if (used[i]) continue;
      used[i] = true;
      value[depth] = i;
      ret += Dfs(depth + 1, alphabet_size, words);
      used[i] = false;
    }
    return ret;
  }
}

int main() {
  int N;
  while (cin >> N, N) {
    vector<string> v(N);
    set<char> alph;
    for (int i = 0; i < N; ++i) {
      cin >> v[i];
      for (int j = 0; j < v[i].size(); ++j)
        alph.insert(v[i][j]);
    }

    string alphabet(alph.begin(), alph.end());

    vector<vector<int> > words(N);
    for (int i = 0; i < v.size(); ++i)
      for (int j = 0; j < v[i].size(); ++j)
        words[i].push_back(alphabet.find(v[i][j]));

    fill(not_zero, not_zero + 10, false);
    for (int i = 0; i < v.size(); ++i)
      if (v[i].size() > 1)
        not_zero[alphabet.find(v[i][0])] = true;

    fill(used, used + 10, false);
    cout << Dfs(0, alphabet.size(), words) << endl;
  }
}

以上64行。
あ、もちろん本番はnext_permutationを使って無駄にカウントしてしまったのを無理矢理factorialで割りつじつま合わせて提出キめました。