Thursday, June 25, 2015

UVa 11987 - Almost Union-Find

Accepted date: 2015-06-25
Language: C++

/*
  UVa 11987 - Almost Union-Find

  To build using Visucal Studio 2012:
    cl -EHsc UVa_11987_Almost_Union-Find.cpp
*/

#include <cstdio>

const int n_max = 100000 + 1;

class almost_union_find {
public:
  void make_set(int i);
  int find_set(int i) const;
  void move(int i, int j);
  void do_union(int i, int j);
  int size(int i) const;
  long long sum(int i) const;

private:
  struct set {
    int size_;
    int head_, tail_;
  };

  struct element {
    int set_;
    int prev_, next_;
  };

  int n_;
  set sets_[n_max];
  element elements_[n_max];
};

void almost_union_find::make_set(int i)
{
  sets_[i].size_ = 1;
  sets_[i].head_ = sets_[i].tail_ = i;
  elements_[i].set_ = i;
  elements_[i].prev_ = elements_[i].next_ = -1;
}

int almost_union_find::find_set(int i) const
{
  return sets_[elements_[i].set_].head_;
}

void almost_union_find::do_union(int i, int j)
{
  if (elements_[i].set_ == elements_[j].set_)
    return;
  set &si = sets_[elements_[i].set_], &sj = sets_[elements_[j].set_];
  if (si.size_ >= sj.size_) {
    si.size_ += sj.size_;
    elements_[sj.head_].prev_ = si.tail_;
    elements_[si.tail_].next_ = sj.head_;
    si.tail_ = sj.tail_;
    for (int next = sj.head_; next != -1; next = elements_[next].next_)
      elements_[next].set_ = elements_[i].set_;
  }
  else {
    sj.size_ += si.size_;
    elements_[si.head_].prev_ = sj.tail_;
    elements_[sj.tail_].next_ = si.head_;
    sj.tail_ = si.tail_;
    for (int next = si.head_; next != -1; next = elements_[next].next_)
      elements_[next].set_ = elements_[j].set_;
  }
}

void almost_union_find::move(int i, int j)
{
  if (elements_[i].set_ == elements_[j].set_)
    return;
  int prev, next;
  set &si = sets_[elements_[i].set_], &sj = sets_[elements_[j].set_];
  if (si.size_ > 1) {
    si.size_--;
    if (si.head_ == i) {
      next = elements_[i].next_;
      si.head_ = next;
      elements_[next].prev_ = -1;
    }
    else if (si.tail_ == i) {
      prev = elements_[i].prev_;
      si.tail_ = prev;
      elements_[prev].next_ = -1;
    }
    else {
      prev = elements_[i].prev_, next = elements_[i].next_;
      elements_[prev].next_ = next, elements_[next].prev_ = prev;
    }
  }
  sj.size_++;
  elements_[i].set_ = elements_[j].set_;
  elements_[sj.tail_].next_ = i;
  elements_[i].prev_ = sj.tail_, elements_[i].next_ = -1;
  sj.tail_ = i;
}

int almost_union_find::size(int i) const
{
  return sets_[elements_[i].set_].size_;
}

long long almost_union_find::sum(int i) const
{
  long long s = 0;
  for (int next = sets_[elements_[i].set_].head_;
    next != -1; next = elements_[next].next_)
    s += next;
  return s;
}

almost_union_find auf;

int main()
{
  int n, m;
  while (scanf("%d %d", &n, &m) != EOF) {
    for (int i = 1; i <= n; i++)
      auf.make_set(i);
    while (m--) {
      int c, p, q;
      scanf("%d", &c);
      switch (c) {
      case 1:
        scanf("%d %d", &p, &q);
        auf.do_union(p, q);
        break;
      case 2:
        scanf("%d %d", &p, &q);
        auf.move(p, q);
        break;
      case 3:
        scanf("%d", &p);
        printf("%d %lld\n", auf.size(p), auf.sum(p));
        break;
      }
    }
  }
  return 0;
}

Tuesday, June 23, 2015

UVa 12348 - Fun Coloring

Accepted date: 2015-06-23
Ranking (as of 2015-06-23): 10 out of 119
Language: C++

/*
  UVa 12348 - Fun Coloring

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_12348_Fun_Coloring.cpp
*/

#include <iostream>
#include <string>
#include <sstream>
#include <cstring>
using namespace std;

const int n_max = 22, m_max = 111, nr_members_max = 3;

struct set {
  int nr_members_;
  int members_[nr_members_max];
} sets[m_max];

int k, n, m;
char colors[n_max + 1];

bool coloring(int mi);

inline bool coloring(int mi, int ci, char rbi)
{
  char pci = colors[ci];
  colors[ci] = rbi;
  bool result = coloring(mi + 1);
  colors[ci] = pci;
  return result;
}

inline bool coloring(int mi, int ci, char rbi, int cj, char rbj)
{
  char pci = colors[ci], pcj = colors[cj];
  colors[ci] = rbi; colors[cj] = rbj;
  bool result = coloring(mi + 1);
  colors[ci] = pci; colors[cj] = pcj;
  return result;
}

inline bool coloring(int mi, int ci, char rbi, int cj, char rbj, int ck, char rbk)
{
  char pci = colors[ci], pcj = colors[cj], pck = colors[ck];
  colors[ci] = rbi; colors[cj] = rbj; colors[ck] = rbk;
  bool result = coloring(mi + 1);
  colors[ci] = pci; colors[cj] = pcj; colors[ck] = pck;
  return result;
}

bool coloring(int mi)
{
  if (mi == m) {
#ifdef DEBUG
    for (int i = 1; i <= n; i++)
      cout << colors[i] << ' ';
    cout << endl;
#endif
    return true;
  }
  else {
    set& st = sets[mi];
    if (st.nr_members_ < 1)
      return false;
    int ci = st.members_[0];
    if (st.nr_members_ < 2) {
      if (colors[ci])
        return coloring(mi + 1);
      else {
        if (coloring(mi, ci, 'R'))
          return true;
        return coloring(mi, ci, 'B');
      }
    }
    int cj = st.members_[1];
    if (st.nr_members_ < 3) {
      if (colors[ci] && colors[cj]) {
        if (colors[ci] == colors[cj])
          return false;
        else
          return coloring(mi + 1);
      }
      else if (!colors[ci] && colors[cj])
        return coloring(mi, ci, (colors[cj] == 'R') ? 'B': 'R');
      else if (colors[ci] && !colors[cj])
        return coloring(mi, cj, (colors[ci] == 'R') ? 'B': 'R');
      else {
        if (coloring(mi, ci, 'R', cj, 'B'))
          return true;
        return coloring(mi, ci, 'B', cj, 'R');
      }
    }
    int ck = st.members_[2];
    char rb;
    if (colors[ci] && colors[cj] && colors[ck]) {
      if (colors[ci] == colors[cj] && colors[ci] == colors[ck])
        return false;
      else
        return coloring(mi + 1);
    }
    else if (!colors[ci] && colors[cj] && colors[ck]) {
      if (colors[cj] ==  colors[ck])
        return coloring(mi, ci, (colors[cj] == 'R') ? 'B' : 'R');
      else {
        if (coloring(mi, ci, 'R'))
          return true;
        return coloring(mi, ci, 'B');
      }
    }
    else if (colors[ci] && !colors[cj] && colors[ck]) {
      if (colors[ci] == colors[ck])
        return coloring(mi, cj, (colors[ci] == 'R') ? 'B' : 'R');
      else {
        if (coloring(mi, cj, 'R'))
          return true;
        return coloring(mi, cj, 'B');
      }
    }
    else if (colors[ci] && colors[cj] && !colors[ck]) {
      if (colors[ci] == colors[cj])
        return coloring(mi, ck, (colors[ci] == 'R') ? 'B' : 'R');
      else {
        if (coloring(mi, ck, 'R'))
          return true;
        return coloring(mi, ck, 'B');
      }
    }
    else if (!colors[ci] && !colors[cj] && colors[ck]) {
      rb = (colors[ck] == 'R') ? 'B' : 'R';
      if (coloring(mi, ci, rb, cj, rb))
        return true;
      if (coloring(mi, ci, 'R', cj, 'B'))
        return true;
      return coloring(mi, ci, 'B', cj, 'R');
    }
    else if (!colors[ci] && colors[cj] && !colors[ck]) {
      rb = (colors[cj] == 'R') ? 'B' : 'R';
      if (coloring(mi, ci, rb, ck, rb))
        return true;
      if (coloring(mi, ci, 'R', ck, 'B'))
        return true;
      return coloring(mi, ci, 'B', ck, 'R');
    }
    else if (colors[ci] && !colors[cj] && !colors[ck]) {
      rb = (colors[ci] == 'R') ? 'B' : 'R';
      if (coloring(mi, cj, rb, ck, rb))
        return true;
      if (coloring(mi, cj, 'R', ck, 'B'))
        return true;
      return coloring(mi, cj, 'B', ck, 'R');
    }
    else {
      if (coloring(mi, ci, 'R', cj, 'R', ck, 'B'))
        return true;
      if (coloring(mi, ci, 'R', cj, 'B', ck, 'R'))
        return true;
      if (coloring(mi, ci, 'B', cj, 'R', ck, 'R'))
        return true;
      if (coloring(mi, ci, 'B', cj, 'B', ck, 'R'))
        return true;
      if (coloring(mi, ci, 'B', cj, 'R', ck, 'B'))
        return true;
      return coloring(mi, ci, 'R', cj, 'B', ck, 'B');
    }
  }
}

int main()
{
  cin >> k;
  while (k--) {
    cin >> n >> m;
    string s;
    getline(cin, s);
    for (int i = 0; i < m; i++) {
      getline(cin, s);
      istringstream iss(s);
      set& st = sets[i];
      st.nr_members_ = 0;
      while (iss >> st.members_[st.nr_members_])
        st.nr_members_++;
    }
    memset(colors, 0, sizeof(colors));
    cout << ((coloring(0)) ? 'Y' : 'N');
  }
  return 0;
}

Sunday, June 21, 2015

UVa 12043 - Divisors

Accepted date: 2015-06-21
Ranking (as of 2015-06-21): 183 out of 501
Language: C++

/*
  UVa 12043 - Divisors

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_12043_Divisors.cpp
*/

#include <cstdio>
#include <cmath>

/*
  for n = p1^e1 * p2^e2 * p3^e3 * ... * pn^en
  number of divisors = (e1 + 1) * (e2 + 1) * (e3 + 1) * ... * (en + 1)
  sum of divisors = ((p1^(e1 + 1) - 1) / (p1 - 1)) * ((p2^(e2 + 1) - 1) / (p2 - 1)) *
    ((p3^(e3 + 1) - 1) / (p3 - 1)) * ... * ((pn^(en + 1) - 1) / (pn - 1))
*/

const int n_max = 100000;
int number_of_divisors[n_max + 1], sum_of_divisors[n_max + 1];
#ifdef __ELAPSED_TIME__
#include <ctime>
#endif

void divisors(int n)
{
  int nn = n, nd = 1, e = 0, i, j;
  long long sd = 1, p = 1;
  for ( ; !(n & 1); n >>= 1) {
    e++;
    p *= 2;
  }
  if (e) {
    nd *= e + 1;
    sd *= p * 2 - 1;
    e = 0, p = 1;
  }
  for (i = 3, j = static_cast<int>(ceil(sqrt(static_cast<double>(n)))); i <= j; ) {
    if (!(n % i)) {
      e++;
      p *= i;
      n /= i;
    }
    else {
      if (e) {
        nd *= e + 1;
        sd *= (p * i - 1) / (i - 1);
        e = 0, p = 1;
      }
      i += 2;
    }
  }
  if (e) {
    nd *= e + 1;
    sd *= (p * i - 1) / (i - 1);
  }
  if (n > 1) {
    nd *= 2;
    sd *= (static_cast<long long>(n) * n - 1) / (n - 1);
  }
  number_of_divisors[nn] = nd;
  sum_of_divisors[nn] = sd;
}

int main()
{
#ifdef __ELAPSED_TIME__
  clock_t start = clock();
#endif
  for (int i = 1; i <= n_max; i++)
    divisors(i);
#ifdef __ELAPSED_TIME__
  fprintf(stderr, "elapsed time = %lf sec.\n",
    static_cast<double>(clock() - start) / CLOCKS_PER_SEC);
#endif
#ifdef DEBUG
  for (int i = 1; i <= n_max; i++)
    printf("%d: %d %lld\n", i, number_of_divisors[i], sum_of_divisors[i]);
#endif
  int T;
  scanf("%d", &T);
  while (T--) {
    int a, b, k;
    scanf("%d %d %d", &a, &b, &k);
    int snd = 0;
    long long ssd = 0;
    for ( ; a <= b; a++)
      if (!(a % k)) {
        snd += number_of_divisors[a];
        ssd += sum_of_divisors[a];
      }
    printf("%d %lld\n", snd, ssd);
  }
  return 0;
}

Saturday, June 20, 2015

UVa 433 - Bank (Not Quite O.C.R.)

Accepted date: 2015-06-20
Ranking (as of 2015-06-20): 6 out of 342
Language: C++

/*
  UVa 433 - Bank (Not Quite O.C.R.)

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_433_Bank.cpp
*/

#include <cstdio>
#include <cstring>

const int nr_digit_columns = 3, nr_digit_rows = 3, nr_digits = 10,
  nr_account_digits = 9;
  char segs[nr_digit_rows][nr_digit_columns * nr_account_digits + 1];
const int digit_patterns[nr_digits] =
  {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};
/*
individual segments of seven-segment display
   GFEDCBA
0: 0111111 3f
1: 0000110 06
2: 1011011 5b
3: 1001111 4f
4: 1100110 66
5: 1101101 6d
6: 1111101 7d
7: 0000111 07
8: 1111111 7f
9: 1101111 6f
*/

struct digit {
  int pattern_, number_, deduced_;
} digits[nr_account_digits];


int read_digit(int di, int ci)
{
  int p = 0;
  if (segs[0][ci + 1] == '_')
    p |= 0x01;
  if (segs[1][ci + 2] == '|')
    p |= 0x02;
  if (segs[2][ci + 2] == '|')
    p |= 0x04;
  if (segs[2][ci + 1] == '_')
    p |= 0x08;
  if (segs[2][ci] == '|')
    p |= 0x10;
  if (segs[1][ci] == '|')
    p |= 0x20;
  if (segs[1][ci + 1] == '_')
    p |= 0x40;
  digits[di].pattern_ = p;
  digits[di].number_ = -1;
  for (int i = 0; i < nr_digits; i++)
    if (digit_patterns[i] == p) {
      digits[di].number_ = i;
      break;
    }
  return digits[di].number_;
}

bool checksum()
{
  int s = 0;
  for (int i = 0, j = 9; i < nr_account_digits; i++, j--) {
    if (digits[i].number_ == -1)
      return false;
    s += digits[i].number_ * j;
  }
  return (s % 11) ? false : true;
}

void print_digits()
{
  for (int i = 0; i < nr_account_digits; i++)
    printf("%c", ((digits[i].number_ != -1) ? '0' + digits[i].number_ : '?'));
  putchar('\n');
}

int main()
{
  int nr_numbers;
  scanf("%d", &nr_numbers);
  while (getchar() != '\n')
    ;
  while (nr_numbers--) {
    memset(segs, 0, sizeof(segs));
    for (int i = 0; i < nr_digit_rows; i++)
      gets(segs[i]);
    int garbled = -1;
    for (int i = 0; i < nr_account_digits; i++)
      if (read_digit(i, i * nr_digit_columns) == -1)
        garbled = i;
#ifdef DEBUG
    print_digits();
#endif
    int ctr = 0;
    if (garbled != -1) {
      digit& d = digits[garbled];
      for (int i = 0; i < nr_digits; i++)
        if (!d.pattern_ ||
          d.pattern_ & digit_patterns[i] && !(d.pattern_ & ~digit_patterns[i])) {
          d.number_ = i;
          if (checksum()) {
            d.deduced_ = i;
            ctr++;
          }
        }
      if (ctr == 1)
        d.number_ = d.deduced_;
    }
    else if (checksum())
      ctr = 1;
    else {
      int di;
      for (int i = 0; i < nr_account_digits && ctr < 2; i++) {
        digit&d = digits[i];
        if (digits[i].pattern_ == 0x7f)
          continue;
        int n = d.number_;
        for (int j = 0; j < nr_digits && ctr < 2; j++)
          if (d.pattern_ & digit_patterns[j] && !(d.pattern_ & ~digit_patterns[j])) {
            d.number_ = j;
            if (checksum()) {
              di = i;
              d.deduced_ = j;
              ctr++;
            }
          }
        d.number_ = n;
      }
      if (ctr == 1)
        digits[di].number_ = digits[di].deduced_;
    }
    if (ctr > 1)
      puts("ambiguous");
    else if (ctr == 1)
      print_digits();
    else
      puts("failure");
  }
  return 0;
}

Thursday, June 18, 2015

UVa 1209 - Wordfish

Accepted date: 2015-06-18
Ranking (as of 2015-06-18): 3 out of 191
Language: C++

/*
  UVa 1209 - Wordfish

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_1209_Wordfish.cpp
*/

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;

const int nr_passwords = 21, nr_letters = 26, nr_chars_max = 20;

int main()
{
  char p[nr_chars_max + 1], passwords[nr_passwords][nr_chars_max + 1];
  while (scanf("%s", p) != EOF) {
    int n = strlen(p), i = nr_passwords / 2, psi, pei;
    strcpy(passwords[i], p);
    for (i++; i < nr_passwords && next_permutation(p, p + n); i++)
      strcpy(passwords[i], p);
    pei = i;
    i = nr_passwords / 2;
    strcpy(p, passwords[i]);
    for (i--; i >= 0 && prev_permutation(p, p + n); i--)
      strcpy(passwords[i], p);
    psi = i + 1;
#ifdef DEBUG
    for (i = psi; i < pei; i++)
      printf("%s, ", passwords[i]);
    putchar('\n');
#endif
    int max_min_d = 0, max_min_d_i;
    for (i = psi; i < pei; i++) {
      int min_d = nr_letters;
      char (&pp)[nr_chars_max + 1] = passwords[i];
      for (int j = 0; j < n - 1; j++)
        min_d = min(min_d, abs(pp[j + 1] - pp[j]));
#ifdef DEBUG
      printf("%s %d\n", passwords[i], min_d);
#endif
      if (min_d > max_min_d) {
        max_min_d = min_d;
        max_min_d_i = i;
      }
    }
    printf("%s%d\n", passwords[max_min_d_i], max_min_d);
  }
  return 0;
}

Wednesday, June 17, 2015

UVa 1262 - Password

Accepted date: 2015-06-17
Ranking (as of 2015-06-17): 2 out of 230
Language: C++

/*
  UVa 1262 - Password

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_1262_Password.cpp
*/

#include <algorithm>
#include <cstdio>
using namespace std;

const int nr_rows = 6, nr_columns = 5;

char first[nr_columns][nr_rows], second[nr_columns][nr_rows],
  common[nr_columns][nr_rows];
int K, lengths[nr_columns];

void read_grid(char grid[nr_columns][nr_rows])
{
  for (int i = 0; i < nr_rows; i++) {
    char s[nr_columns + 1];
    scanf("%s", s);
    for (int j = 0; j < nr_columns; j++)
      grid[j][i] = s[j];
  }
  for (int i = 0; i < nr_columns; i++) {
    char (&g)[nr_rows] = grid[i];
    sort(g, g + nr_rows);
#ifdef DEBUG
    printf("%c%c%c%c%c%c\n", g[0], g[1], g[2], g[3], g[4], g[5]);
#endif
  }
}

bool password(int ci, char s[nr_columns + 1])
{
  if (ci == nr_columns) {
    K--;
    return !K;
  }
  else {
    for (int i = 0; i < lengths[ci]; i++) {
      s[ci] = common[ci][i];
      if (password(ci + 1, s))
        return true;
    }
    return false;
  }
}

int main()
{
  int T;
  scanf("%d", &T);
  while (T--) {
    scanf("%d", &K);
    read_grid(first);
    read_grid(second);
    for (int i = 0; i < nr_columns; i++) {
      int l = 0;
      char (&f)[nr_rows] = first[i], (&s)[nr_rows] = second[i],
        (&c)[nr_rows] = common[i];
      for (int fi = 0, si = 0; fi < nr_rows && si < nr_rows; ) {
        char fc = f[fi], sc = s[si];
        if (fc == sc) {
          c[l++] = fc;
          for (fi++; fi < nr_rows && f[fi] == fc; fi++)
            ;
          for (si++; si < nr_rows && s[si] == sc; si++)
            ;
        }
        else if (fc < sc) {
          for (fi++; fi < nr_rows && f[fi] == fc; fi++)
            ;
        }
        else {
          for (si++; si < nr_rows && s[si] == sc; si++)
            ;
        }
      }
      lengths[i] = l;
    }
    int k = 1;
    for (int i = 0; i < nr_columns; i++)
      k *= lengths[i];
    if (k < K)
      puts("NO");
    else {
      char s[nr_columns + 1];
      s[nr_columns] = '\0';
      password(0, s);
      printf("%s\n", s);
    }
  }
  return 0;
}

Monday, June 15, 2015

UVa 11961 - DNA

Accepted date: 2015-06-15
Ranking (as of 2015-06-15): 85 out of 109
Language: C++

/*
  UVa 11961 - DNA

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_11961_DNA.cpp
*/

#include <iostream>
#include <set>
#include <cstring>
using namespace std;

const int N_max = 15, nr_nucleotides = 4;
const char nucleotides[nr_nucleotides] = {'A', 'C', 'G', 'T'};

struct Dna {
  char s_[N_max + 1];
  bool operator<(const Dna& d) const {return strcmp(s_, d.s_) < 0;}
};

int main()
{
  int T;
  cin >> T;
  while (T--) {
    int N, K;
    cin >> N >> K;
    Dna d;
    cin >> d.s_;
    set<Dna> current;
    current.insert(d);
    while (K--) {
      set<Dna> next;
      for (set<Dna>::const_iterator ci = current.begin(), ce = current.end();
        ci != ce; ++ci) {
        Dna d = *ci;
        for (int i = 0; i < N; i++) {
          char nucleotide = d.s_[i];
          for (int j = 0; j < nr_nucleotides; j++)
            if (nucleotide != nucleotides[j]) {
              d.s_[i] = nucleotides[j];
              if (current.find(d) == ce)
                next.insert(d);
            }
          d.s_[i] = nucleotide;
        }
      }
      current.insert(next.begin(), next.end());
    }
    cout << current.size() << endl;
    for (set<Dna>::const_iterator ci = current.begin(), ce = current.end();
      ci != ce; ++ci)
      cout << ci->s_ << endl;
  }
  return 0;
}

Monday, June 8, 2015

UVa 12249 - Overlapping Scenes

Accepted date: 2015-06-08
Ranking (as of 2015-06-08): 7 out of 107
Language: C++

/*
  UVa 12249 - Overlapping Scenes

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_12249_Overlapping_Scenes.cpp
*/

#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;

int main()
{
  const int n_max = 6, nr_chars_max = 10;
  int T;
  scanf("%d", &T);
  for (int t = 1; t <= T; t++) {
    int n;
    scanf("%d", &n);
    int scenes[n_max], scene_string_lengths[n_max], min_length = 0;
    char scene_strings[n_max][nr_chars_max + 1],
      merged_string[n_max * nr_chars_max + 1];
    for (int i = 0; i < n; i++) {
      scenes[i] = i;
      scanf("%s", scene_strings[i]);
      scene_string_lengths[i] = strlen(scene_strings[i]);
      min_length += scene_string_lengths[i];
    }
    do {
      strcpy(merged_string, scene_strings[scenes[0]]);
      for (int i = 1; i < n; i++) {
        int j, k = strlen(merged_string);
        for (j = 0; j < k; j++)
          if (!memcmp(&merged_string[j], &scene_strings[scenes[i]][0], k - j))
            break;
        strcat(merged_string, &scene_strings[scenes[i]][k - j]);
      }
#ifdef DEBUG
      printf("%s\n", merged_string);
#endif
      min_length = min(min_length, static_cast<int>(strlen(merged_string)));
    } while (next_permutation(scenes, scenes + n));
    printf("Case %d: %d\n", t, min_length);
  }
  return 0;
}

Friday, June 5, 2015

UVa 868 - Numerical Maze

Accepted date: 2015-06-05
Ranking (as of 2015-06-05): 19 out of 191
Language: C++

/*
  UVa 868 - Numerical Maze

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_868_Numerical_Maze.cpp
*/

#include <iostream>
#include <vector>
#include <queue>
#include <utility>
using namespace std;

const int nr_dirs = 4;
const pair<int, int> dirs[nr_dirs] =
  {make_pair(1, 0), make_pair(-1, 0), make_pair(0, 1), make_pair(0, -1)};

struct path {
  int i_, j_;
  int next_, last_;

  path() {}
  path(int i, int j, int next, int last) : i_(i), j_(j), next_(next), last_(last) {}
};

void bfs(int r, int c, int cj, const vector< vector<int> >& maze, path& min_path)
{
  min_path.j_ = c;
  queue<path> q;
  q.push(path(0, cj, 1, 2));
  while (!q.empty()) {
    path p = q.front(); q.pop();
    if (p.i_ == r - 1) {
      if (p.j_ < min_path.j_)
        min_path = p;
    }
    else {
      for (int i = 0; i < nr_dirs; i++) {
        int ni = p.i_ + dirs[i].first, nj = p.j_ + dirs[i].second;
        if (ni >= 0 && ni < r && nj >= 0 && nj < c &&
          maze[ni][nj] == p.next_) {
          int next = p.next_, last = p.last_;
          if (next == last) {
            next = 1; last++;
          }
          else
            next++;
          q.push(path(ni, nj, next, last));
        }
      }
    }
  }
}

int main()
{
  int nr_cases;
  cin >> nr_cases;
  while (nr_cases--) {
    int N, M;
    cin >> N >> M;
    vector< vector<int> > maze(N, vector<int>(M));
    for (int i = 0; i < N; i++)
      for (int j = 0; j < M; j++)
        cin >> maze[i][j];
    int min_j;
    path min_path;
    min_path.j_ = M;
    for (int j = 0; j < M; j++)
      if (maze[0][j] == 1) {
        path p;
        bfs(N, M, j, maze, p);
        if (p.j_ < min_path.j_) {
          min_j = j;
          min_path = p;
          break;
        }
      }
    cout << "1 " << min_j + 1 << endl;
    cout << N << ' ' << min_path.j_ + 1 << endl;
    if (nr_cases)
      cout << endl;
  }
  return 0;
}

UVa 234 - Switching Channels

Accepted date: 2015-06-04
Language: C++

/*
  UVa 234 - Switching Channels

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_234_Switching_Channels.cpp
*/

#include <algorithm>
#include <limits>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;

const int p_max = 8, a_max = 8, il_max = 5;

int programs[p_max];

struct alignment_point {
  int il_, t_;
} alignment_points[a_max];

int main()
{
  for (int ds = 1; ; ds++) {
    int p, a;
    scanf("%d", &p);
    if (!p)
      break;
    for (int i = 0; i < p; i++)
      scanf("%d", &programs[i]);
    scanf("%d", &a);
    int il = 0; // inportance level
    for (int i = 0; i < a; i++) {
      scanf("%d %d", &alignment_points[i].il_, &alignment_points[i].t_);
      il = max(il, alignment_points[i].il_);
    }
    sort(programs, programs + p);
    int min_err = -1, min_programs[p_max], min_miss_times[il_max + 1];
    do {
      int tm = 0, times[p_max + 1], miss_times[il_max + 1], err = 0;
      for (int i = 0; i < p; i++) {
        times[i] = tm;
        tm += programs[i];
      }
      times[p] = tm;
      memset(miss_times, 0, sizeof(miss_times));
      for (int i = 0; i < a; i++) {
        int t = alignment_points[i].t_, il = alignment_points[i].il_,
          mt = numeric_limits<int>::max();
        for (int j = 0; j <= p; j++)
          mt = min(mt, abs(times[j] - t));
        miss_times[il] += mt;
        err += mt;
      }
#ifdef DEBUG
        for (int i = 0; i < p; i++)
          printf("%d%c", programs[i], ((i < p - 1) ? ' ' : ':'));
        putchar(' ');
        for (int i = 1; i <= il; i++)
          printf("%d%c", miss_times[i], ((i < il) ? ' ' : ':'));
        printf(" %d", err);
#endif
      bool better = false;
      if (min_err == -1)
        better = true;
      else {
        for (int i = 1; i <= il; i++) {
          if (miss_times[i] < min_miss_times[i]) {
            better = true; break;
          }
          else if (miss_times[i] > min_miss_times[i])
            break;
        }
      }
#ifdef DEBUG
      puts((better) ? " better" : "");
#endif
      if (better) {
        min_err = err;
        memcpy(min_programs, programs, sizeof(int) * p);
        memcpy(min_miss_times, miss_times, sizeof(int) * (il + 1));
#ifndef DEBUG
        if (!min_err)
          break;
#endif
      }
    } while (next_permutation(programs, programs + p));
    printf("Data set %d\n", ds);
    printf("Order: ");
    for (int i = 0; i < p; i++)
      printf("%d%c", min_programs[i], ((i < p - 1) ? ' ' : '\n'));
    printf("Error: %d\n", min_err);
/*
    printf("Data set %d\n", ds);
    printf("  Order: ");
    for (int i = 0; i < p; i++)
      printf("%d%c", min_programs[i], ((i < p - 1) ? ' ' : '\n'));
    printf("  Error: %d\n", min_err);
*/
  }
  return 0;
}

Monday, June 1, 2015

UVa 830 - Shark

Accepted date: 2015-06-01
Ranking (as of 2015-06-01): 33 out of 160
Language: C++

/*
  UVa 830 - Shark

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_830_Shark.cpp
*/

#include <cstdio>
#include <cstring>
#include <cctype>

enum {sardine, mackerel, salmon, grouper, turtle, dolphin, whale, shark};
#ifdef DEBUG
const char* names[] = {"sardine", "mackerel", "salmon", "grouper", "turtle",
  "dolphin", "whale", "shark"};
#endif
const int nr_shapes = shark - sardine + 1;
const int L_max = 64, C_max = 64;
char grid[L_max][C_max + 1];

int clear_shape(int L, int C, int ls, int cs, int w, int c)
{
  int i, j, h = 0;
  for (i = ls; i < L; i++, h++)
    for (j = cs; j < cs + w; j++) {
      if (grid[i][j] != c)
        return h;
      grid[i][j] = '\0';
    }
  return h;
}

int shape(int L, int C, int ls, int cs)
{
  int j, w = 1, h;
  char c = grid[ls][cs];
  for (j = cs + 1; j < C; j++, w++)
    if (grid[ls][j] != c)
      break;
  switch (w) {
  case 1:
    if (ls + 1 < L && cs && cs + 1 < C && grid[ls + 1][cs - 1] == c &&
      grid[ls + 1][cs] == c && grid[ls + 1][cs + 1] == c) {
      grid[ls][cs] = '\0';
      clear_shape(L, C, ls + 1, cs - 1, 3, c);
      return shark;
    }
    else {
      h = clear_shape(L, C, ls, cs, 1, c);
      return (h > 2) ? salmon : ((h == 2) ? mackerel : sardine);
    }
  case 2:
    h = clear_shape(L, C, ls, cs, 2, c);
    return ((h > 2) ? grouper : (h == 2) ? turtle : mackerel);
  case 3:
    h = clear_shape(L, C, ls, cs, 3, c);
    if (h > 3) {
      if (ls + h < L && grid[ls + h][cs + 1] == c) {
        grid[ls + h][cs + 1] = '\0';
        return shark;
      }
      else
        return dolphin;
    }
    else
      return (h == 3) ? turtle : ((h == 2) ? grouper : salmon);
  case 4:
    h = clear_shape(L, C, ls, cs, 4, c);
    if (h > 4)
      return whale;
    else if (h == 3) {
      if (cs && grid[ls + 1][cs - 1] == c) {
        grid[ls + 1][cs - 1] = '\0';
        return shark;
      }
      else if (cs + 4 < C && grid[ls + 1][cs + 4] == c) {
        grid[ls + 1][cs + 4] = '\0';
        return shark;
      }
      else
        return dolphin;
    }
    else
      return (h == 4) ? turtle : ((h == 2) ? grouper : salmon);
  default:
    h = clear_shape(L, C, ls, cs, w, c);
    if (h > 4)
      return turtle;
    else if (h == 3) {
      if (cs && grid[ls + 1][cs - 1] == c) {
        grid[ls + 1][cs - 1] = '\0';
        return shark;
      }
      else if (cs + 4 < C && grid[ls + 1][cs + 4] == c) {
        grid[ls + 1][cs + 4] = '\0';
        return shark;
      }
      else
        return dolphin;
    }
    else
      return (h == 4) ? whale : ((h == 2) ? grouper : salmon);
  }
}

int main()
{
  int nr_cases;
  scanf("%d", &nr_cases);
  while (nr_cases--) {
    int L, C;
    scanf("%d %d", &L, &C);
    for (int i = 0; i < L; i++)
      scanf("%s", grid[i]);
    int shapes[nr_shapes];
    memset(shapes, 0, sizeof(shapes));
    for (int i = 0; i < L; i++)
      for (int j = 0; j < C; j++)
        if (islower(grid[i][j])) {
          int s = shape(L, C, i, j);
#ifdef DEBUG
          printf("(%2d, %2d) %s\n", i, j, names[s]);
#endif
          shapes[s]++;
        }
    for (int i = 0; i < nr_shapes; i++)
      printf("%d%c", shapes[i], ((i < nr_shapes - 1) ? ' ' : '\n'));
    if (nr_cases)
      putchar('\n');
  }
  return 0;
}