Tuesday, December 26, 2017

UVa 12694 - Meeting Room Arrangement

Accepted date: 2017-12-26
Run Time: 0.000
Ranking (as of 2017-12-26): 169 out of 391
Language: C++

A straight-forward interval scheduling problem.


/*
  UVa 12694 - Meeting Room Arrangement

  To build using Visual Studio 2015:
    cl -EHsc -O2 UVa_12694_Meeting_Room_Arrangement.cpp
*/

/*
  A straight forward interval scheduling problem.
*/

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

const int nr_events_max = 20;

struct event {
  int s_, f_;

  bool operator<(const event& e) const {return f_ < e.f_;}
} events[nr_events_max];

int main()
{
  int n;
  scanf("%d", &n);
  while (n--) {
    int nr_events = 0;
    for ( ; ; nr_events++) {
      scanf("%d %d", &events[nr_events].s_, &events[nr_events].f_);
      if (!events[nr_events].s_ && !events[nr_events].f_)
        break;
    }
    int max_nr_events = 0;
    if (nr_events) {
      sort(events, events + nr_events);
        // sort the events in ascending order of their finish times
      max_nr_events = 1;
      int f = events[0].f_;
      for (int i = 1; i < nr_events; i++)
        if (events[i].s_ >= f) {
          max_nr_events++;
          f = events[i].f_;
        }
    }
    printf("%d\n", max_nr_events);
  }
  return 0;
}

Thursday, July 13, 2017

UVa 1231 - ACORN

Accepted date: 2017-07-13
Run Time: 0.260
Ranking (as of 2017-07-13): 114 out of 373
Language: C++

/*
  UVa 1231 - ACORN

  To build using Visual Studio 2015:
    cl -EHsc -O2 UVa_1231_ACORN.cpp

  This is an accepted solution.
*/

#include <algorithm>
#include <cstdio>
#ifdef __ELAPSED_TIME__
#include <ctime>
#endif
using namespace std;

const int t_max = 2000, h_max = 2000;

int acorns[t_max][h_max + 1];
  // acorns[i][j] is the number of acorns at height j on the i-th tree
int collections[t_max][h_max + 1];
  // collections[i][j] is the max. number of acorns collected at height j on the i-th tree
int max_collections[h_max + 1];
  // max_collections[j] is the max. number of acorns collected at height j

int main()
{
#ifdef __ELAPSED_TIME__
  clock_t start = clock();
#endif
  int c;
  scanf("%d", &c);
  while (c--) {
    int t, h, f;
    scanf("%d %d %d", &t, &h, &f);
    for (int j = 1; j <= h; j++) {
      for (int i = 0; i < t; i++)
        acorns[i][j] = collections[i][j] = 0;
      max_collections[j] = 0;
    }
    for (int i = 0; i < t; i++) {
      int a;
      scanf("%d", &a);
      while (a--) {
        int n;
        scanf("%d", &n);
        acorns[i][n]++;
      }
    }
    for (int j = 1; j <= h; j++)
      for (int i = 0; i < t; i++) {
        collections[i][j] = collections[i][j - 1];
        if (j > f)
          collections[i][j] = max(collections[i][j], max_collections[j - f]);
        collections[i][j] += acorns[i][j];
        max_collections[j] = max(max_collections[j], collections[i][j]);
      }
    printf("%d\n", max_collections[h]);
  }
  scanf("%*d");
#ifdef __ELAPSED_TIME__
  fprintf(stderr, "elapsed time = %lf sec.\n",
    static_cast<double>(clock() - start) / CLOCKS_PER_SEC);
#endif
  return 0; // discard "0"
}

Saturday, July 8, 2017

UVa 13130 - Cacho

Accepted date: 2017-07-08
Run Time: 0.000
Ranking (as of 2017-07-08): 336 out of 384
Language: C++

/*
  UVa 13130 - Cacho

  To build using Visual Studio 2015:
    cl -EHsc -O2 UVa_13130_Cacho.cpp
*/

#include <cstdio>

int main()
{
  int T;
  scanf("%d", &T);
  while (T--) {
    int a1, a2, a3, a4, a5;
    scanf("%d %d %d %d %d", &a1, &a2, &a3, &a4, &a5);
    puts(
      (a1 == 1 && a2 == 2 && a3 == 3 && a4 == 4 && a5 == 5 ||
      a1 == 2 && a2 == 3 && a3 == 4 && a4 == 5 && a5 == 6) ? "Y" : "N");
  }
  return 0;
}

Thursday, March 30, 2017

UVa 11488 - Hyper Prefix Sets

Accepted date: 2017-03-30
Run Time: 0.110
Ranking (as of 2017-03-30): 64 out of 555
Language: C++

Used trie.
During the construction of trie, counted the number of occurrences of each trie node and also calculated the goodness for the node.


/*
  UVa 11488 - Hyper Prefix Sets

  To build using Visual Studio 2015:
    cl -EHsc -O2 UVa_11488_Hyper_Prefix_Sets.cpp
*/

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

const int nr_letters = '1' - '0' + 1, nr_chars_max = 200;

struct trie_node {
  static int max_goodness;

  int ctr_;
  trie_node* children_[nr_letters];

  trie_node() : ctr_(0) {
    memset(children_, 0, sizeof(children_));
  }
  ~trie_node() {
    for (int i = 0; i < nr_letters; i++)
      delete children_[i];
  }
  void insert(const char* s);
  void calculate_goodness(int length);
};

int trie_node::max_goodness;

void trie_node::insert(const char* s)
{
  trie_node* p = this;
  for (int i = 0, length = strlen(s); i < length; i++) {
    int j = s[i] - '0';
    if (!p->children_[j])
      p->children_[j] = new trie_node();
    p = p->children_[j];
    p->ctr_++;
    max_goodness = max(max_goodness, (i + 1) * p->ctr_);
  }
}

int main()
{
  int T;
  scanf("%d", &T);
  while (T--) {
    int n;
    scanf("%d", &n);
    trie_node::max_goodness = 0;
    trie_node* root = new trie_node();
    while (n--) {
      char s[nr_chars_max + 1];
      scanf("%s", s);
      root->insert(s);
    }
    printf("%d\n", trie_node::max_goodness);
    delete root;
  }
  return 0;
}

Friday, March 24, 2017

UVa 298 - Race Tracks

Accepted date: 2017-03-24
Run Time: 0.050
Ranking (as of 2017-03-24): 74 out of 369
Language: C++

/*
  UVa 298 - Race Tracks

  To build using Visual Studio 2015:
    cl -EHsc -O2 UVa_298_Race_Tracks.cpp
*/

#include <queue>
#include <limits>
#include <cstdio>
using namespace std;

const int infinite = numeric_limits<int>::max();
const int X_max = 30, Y_max = 30, v_min = -3, v_max = 3, vc_min = -1, vc_max = 1;
const int nr_vs = v_max - v_min + 1;

int nr_hops[X_max][Y_max][nr_vs][nr_vs];
  // nr_hops[x][y][vx - v_min][vy - v_min] is the number of hops at (x, y) 
  // with the velocity of (vx, vy)

bool obstacles[X_max][Y_max]; // obstacles[x][y] is true if there is an obstacle at (x, y)

struct path {
  int x_, y_, vx_, vy_, nr_;
  path(int x, int y, int vx, int vy, int nr) : x_(x), y_(y), vx_(vx), vy_(vy), nr_(nr) {}
};

int main()
{
  int N;
  scanf("%d", &N);
  while (N--) {
    int X, Y;
    scanf("%d %d", &X, &Y);
    for (int i = 0; i < X; i++)
      for (int j = 0; j < Y; j++) {
        obstacles[i][j] = false;
        for (int vi = 0; vi < nr_vs; vi++)
          for (int vj = 0; vj < nr_vs; vj++)
            nr_hops[i][j][vi][vj] = infinite;
      }
    int sx, sy, fx, fy;
    scanf("%d %d %d %d", &sx, &sy, &fx, &fy);
    int P;
    scanf("%d", &P);
    while (P--) {
      int x1, x2, y1, y2;
      scanf("%d %d %d %d", &x1, &x2, &y1, &y2);
      for (int i = x1; i <= x2; i++)
        for (int j = y1; j <= y2; j++)
          obstacles[i][j] = true;
    }
    queue<path> q;
    nr_hops[sx][sy][-v_min][-v_min] = 0;
    q.push(path(sx, sy, -v_min, -v_min, 0));
    while (!q.empty()) {
      path p = q.front();
      q.pop();
#ifdef DEBUG
      printf("(%d, %d) with v(%d, %d): %d\n",
        p.x_, p.y_, p.vx_ + v_min, p.vy_ + v_min, p.nr_);
#endif
      int nr = p.nr_ + 1;
      for (int vcx = vc_min; vcx <= vc_max; vcx++) {
        int vx = p.vx_ + v_min + vcx;
        if (vx < v_min || vx > v_max)
          continue;
        int x = p.x_ + vx;
        if (x < 0 || x >= X)
          continue;
        for (int vcy = vc_min; vcy <= vc_max; vcy++) {
          int vy = p.vy_ + v_min + vcy;
          if (vy < v_min || vy > v_max)
            continue;
          int y = p.y_ + vy;
          if (y < 0 || y >= Y || obstacles[x][y])
            continue;
          if (nr_hops[x][y][vx - v_min][vy - v_min] <= nr)
            continue;
#ifdef DEBUG
      printf("  (%d, %d) with v(%d, %d): %d\n",
        x, y, vx + v_min, vy + v_min, nr);
#endif
          nr_hops[x][y][vx - v_min][vy - v_min] = nr;
          q.push(path(x, y, vx - v_min, vy - v_min, nr));
        }
      }
    }
    int nr = infinite;
    for (int vi = 0; vi < nr_vs; vi++)
      for (int vj = 0; vj < nr_vs; vj++)
        if (nr_hops[fx][fy][vi][vj] < nr)
          nr = nr_hops[fx][fy][vi][vj];
    if (nr < infinite)
      printf("Optimal solution takes %d hops.\n", nr);
    else
      puts("No solution.");
  }
  return 0;
}

Tuesday, March 21, 2017

UVa 1600 - Patrol Robot

Accepted date: 2017-03-21
Run Time: 0.000
Ranking (as of 2017-03-21): 211 out of 369
Language: C++
/*
  UVa 1600 - Patrol Robot

  To build using Visual Studio 2015:
    cl -EHsc -O2 UVa_1600_Patrol_Robot.cpp
*/

#include <queue>
#include <limits>
#include <cstdio>
#include <cstring>
using namespace std;

const int infinite = numeric_limits<int>::max();
const int m_max = 20, n_max = 20, k_max = 20;

const int nr_dirs = 4;
const int dirs[nr_dirs][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};

int obstacles[m_max][n_max];
  // obstacles[i][j] is 1 if there is an obstacle at cell(i, j), 0 otherwise
int nr_moves[m_max][n_max][k_max + 1];
  // nr_moves[i][j][k] is the minimum number of moves from (0, 0) to (i, j) 
  // with the turbo mode used for k cells

struct path {
  int i_, j_, k_, nr_;
  path(int i, int j, int k, int nr) : i_(i), j_(j), k_(k), nr_(nr) {}
};

int main()
{
  int ns;
  scanf("%d", &ns);
  while (ns--) {
    int m, n, k;
    scanf("%d %d", &m, &n);
    scanf("%d", &k);
    for (int i = 0; i < m; i++)
      for (int j = 0; j < n; j++) {
        scanf("%d", &obstacles[i][j]);
        for (int l = 0; l <= k; l++)
          nr_moves[i][j][l] = infinite;
      }
    queue<path> q;
    nr_moves[0][0][0] = 0;
    q.push(path(0, 0, 0, nr_moves[0][0][0]));
    while (!q.empty()) {
      path p = q.front(); q.pop();
#ifdef DEBUG
      printf("[%d][%d][%d]: %d\n", p.i_, p.j_, p.k_, p.nr_);
#endif
      for (int d = 0; d < nr_dirs; d++) {
        int i = p.i_ + dirs[d][0], j = p.j_ + dirs[d][1], l = p.k_;
        if (i < 0 || i >= m || j < 0 || j >= n)
          continue;
        if (obstacles[i][j]) {
          if (l + 1 <= k && p.nr_ + 1 < nr_moves[i][j][l + 1]) {
            nr_moves[i][j][l + 1] = p.nr_ + 1;
            q.push(path(i, j, l + 1, nr_moves[i][j][l + 1]));
          }
        }
        else {
          if (p.nr_ + 1 < nr_moves[i][j][0]) {
            nr_moves[i][j][0] = p.nr_ + 1;
            q.push(path(i, j, 0, nr_moves[i][j][0]));
          }
        }
      }
    }
    int nr = infinite;
    for (int l = 0; l <= k; l++)
      if (nr_moves[m - 1][n - 1][l] < nr)
        nr = nr_moves[m - 1][n - 1][l];
    printf("%d\n", (nr < infinite) ? nr : -1);
  }
  return 0;
}

UVa 12893 - Count It

Accepted date: 2017-03-21
Run Time: 0.000
Ranking (as of 2017-03-21): 133 out of 364
Language: C++

/*
  UVa 12893 - Count It

  To build using Visual Studio 2015:
    cl -EHsc -O2 UVa_12893_Count_It.cpp
*/

#include <cstdio>

long long count_it(long long n)
{
  if (!n)
    return 0;
  long long cn = count_it(n / 2);
  if (n & 1)
    cn++;
  return cn;
}

int main()
{
  int T;
  scanf("%d", &T);
  while (T--) {
    long long n;
    scanf("%lld", &n);
    printf("%lld\n", count_it(n));
  }
  return 0;
}

UVa 210 - Concurrency Simulator

Accepted date: 2017-03-21
Run Time: 0.260
Ranking (as of 2017-03-21): 211 out of 370
Language: C++

/*
  UVa 210 - Concurrency Simulator

  To build using Visual Studio 2015:
    cl -EHsc -O2 UVa_210_Concurrency_Simulator.cpp
*/

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

const int nr_programs_max = 10, nr_statements_max = 26;

enum {st_assignment, st_output, st_lock, st_unlock, st_end};
const int nr_statement_types = st_end - st_assignment + 1;

struct statement {
  int type_;
  int variable_, value_;
};

struct program {
  int current_; // current statement
  int remaining_; // number of remaining statements
  statement statements_[nr_statements_max];
} programs[nr_programs_max];

const int nr_variables = 'z' - 'a' + 1;
int values[nr_variables];
int nr_programs, execution_times[nr_statement_types], quantum;

deque<int> ready_queue, blocked_queue;

int main()
{
  string s;
  getline(cin, s);
  istringstream iss(s);
  int nr_cases;
  iss >> nr_cases;
  iss.clear();
  while (nr_cases--) {
    getline(cin, s); // a blank line
    getline(cin, s);
    iss.str(s);
    iss >> nr_programs;
    for (int i = 0; i < nr_statement_types; i++)
      iss >> execution_times[i];
    iss >> quantum;
    iss.clear();
    memset(values, 0, sizeof(values));
    for (int i = 0; i < nr_programs; i++) {
      program& p = programs[i];
      p.current_ = p.remaining_ = 0;
      do {
        getline(cin, s);
        iss.str(s);
        string t, u;
        iss >> t;
        statement& st = p.statements_[p.remaining_++];
        if (t == "print") {
          iss >> u;
          st.type_ = st_output, st.variable_ = u[0] - 'a';
        }
        else if (t == "lock")
          st.type_ = st_lock;
        else if (t == "unlock")
          st.type_ = st_unlock;
        else if (t == "end")
          st.type_ = st_end;
        else {
          st.type_ = st_assignment, st.variable_ = t[0] - 'a';
          iss >> u >> st.value_;
        }
        iss.clear();
      } while (p.statements_[p.remaining_ - 1].type_ != st_end);
#ifdef DEBUG
      cout << i << ": " << p.remaining_ << " stateemtns\n";
#endif
      ready_queue.push_back(i);
    }
    bool locked = false;
    while (!ready_queue.empty()) {
      int i = ready_queue.front();
      ready_queue.pop_front();
      program& p = programs[i];
      int q = quantum;
      bool blocked = false;
      do {
        statement& st = p.statements_[p.current_];
        q -= execution_times[st.type_];
        switch (st.type_) {
        case st_assignment:
          values[st.variable_] = st.value_;
          p.current_++, p.remaining_--;
          break;
        case st_output:
          cout << i + 1 << ": " << values[st.variable_] << endl;
          p.current_++, p.remaining_--;
          break;
        case st_lock:
          if (locked) {
            blocked_queue.push_back(i);
            q = -1, blocked = true;
          }
          else {
            locked = true;
            p.current_++, p.remaining_--;
          }
          break;
        case st_unlock:
          if (!blocked_queue.empty()) {
            int j = blocked_queue.front();
            blocked_queue.pop_front();
            ready_queue.push_front(j);
          }
          locked = false;
          p.current_++, p.remaining_--;
          break;
        case st_end:
          p.current_++, p.remaining_--;
          break;
        }
#ifdef DEBUG
      cout << i + 1 << ": " << p.current_ << ' ' << p.remaining_ << ' ' << q << endl;
#endif
      } while (p.remaining_ && q > 0);
      if (p.remaining_&& !blocked)
        ready_queue.push_back(i);
    }
    if (nr_cases)
      cout << endl;
  }
  return 0;
}

Monday, March 20, 2017

UVa 12908 - The book thief

Accepted date: 2017-03-20
Run Time: 0.070
Ranking (as of 2017-03-20): 80 out of 374
Language: C++

/*
  UVa 12908 - The book thief

  To build using Visual Studio 2015:
    cl -EHsc -O2 UVa_12908_The_book_thief.cpp
*/

#include <cstdio>
#include <cmath>

int main()
{
  while (true) {
    int s;
    scanf("%d", &s);
    if (!s)
       break;
    int n = static_cast<int>(ceil((-1.0 + sqrt(1.0 + 8.0 * s)) / 2.0));
    if (n * (n + 1) / 2 == s)
      n++;
    printf("%d %d\n", n * (n + 1) / 2 - s, n);
  }
  return 0;
}

Thursday, January 19, 2017

UVa 1590 - IP Networks

Accepted date: 2017-01-19
Run Time: 0.000
Ranking (as of 2017-01-19): 90 out of 362
Language: C++

Network_address = IP_address & Network_mask.
And for all IP addresses, Network address should be the same.


/*
  UVa 1590 - IP Networks

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

#include <cstdio>

const int m_max = 1000;
unsigned int ip_addresses[m_max];

void print_address(unsigned int address)
{
  printf("%u.%u.%u.%u\n", (address & 0xff000000) >> 24, (address & 0x00ff0000) >> 16,
    (address & 0x0000ff00) >> 8, address & 0x000000ff);
}

int main()
{
  const int nr_bits = 32;
  int m;
  while (scanf("%d", &m) != EOF) {
    for (int i = 0; i < m;i++) {
      int b0, b1, b2, b3;
      scanf("%d.%d.%d.%d", &b0, &b1, &b2, &b3);
      ip_addresses[i] = b0 << 24 | b1 << 16 | b2 << 8 | b3;
    }
    unsigned int mask = 0xffffffff, b = 1, address;
    for (int i = 0; i <= nr_bits; i++, mask &= ~b, b <<= 1) {
      address = ip_addresses[0] & mask;
      int j;
      for (j = 1; j < m; j++)
        if ((ip_addresses[j] & mask) != address)
          break;
      if (j == m)
        break;
    }
    print_address(address);
    print_address(mask);
  }
  return 0;
}

Tuesday, January 17, 2017

UVa 12321 - Gas Stations

Accepted date: 2017-01-17
Run Time: 0.030
Ranking (as of 2017-01-17): 79 out of 357
Language: C++

/*
  UVa 12321 - Gas Stations

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

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

const int G_max = 10000;

struct coverage {
  int l_, h_; // coverage is from l_ to h_

bool operator<(const coverage& c) const {return (l_ != c.l_) ? l_ < c.l_ : h_ < c.h_;}
} coverages[G_max];

int main()
{
  while (true) {
    int L, G;
    scanf("%d %d", &L, &G);
    if (!L)
      break;
    for (int i = 0; i < G; i++) {
      int xi, ri;
      scanf("%d %d", &xi, &ri);
      coverages[i].l_ = max(xi - ri, 0), coverages[i].h_ = min(xi + ri, L);
    }
    sort(coverages, coverages + G); // sort the stations by thier lower ends
#ifdef DEBUG
    for (int i = 0; i < G; i++)
      printf("[%d %d]%c", coverages[i].l_, coverages[i].h_, ((i < G - 1) ? ' ' : '\n'));
#endif
    int i = 0, h = 0, l = 0, nr = 0;
    for ( ; l < L && i < G; i++) {
      // discard the stations whose lower end is covered by other station
      const coverage& c = coverages[i];
      if (c.l_ > l) {
        if (c.l_ <= h) {
          l = h, h = 0, nr++;
          if (l == L)
            break;
        }
        else
          break;
      }
      h = max(h, c.h_);
    }
    if (h)
      l = h, nr++;
    printf("%d\n", (l == L) ? G - nr : -1);
  }
  return 0;
}

Saturday, January 14, 2017

UVa 11926 - Multitasking

Accepted date: 2014-07-29
First verdict date: 2014-07-29
Last verdict date: 2016-12-20
Run Time: 0.000
Ranking (as of 2017-01-14): 239 out of 1233
Language: C++

/*
  UVa 11926 - Multitasking

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

#include <cstdio>
#include <cstring>

const int minutes_max = 1000000;

bool minutes[minutes_max + 1];

int main()
{
  while (true) {
    int n, m;
    scanf("%d %d", &n, &m);
    if (!n && !m)
      break;
    memset(minutes, 0, sizeof(minutes));
    bool conflict = false;
    while (n--) {
      int st, et;
      scanf("%d %d", &st, &et);
      if (conflict)
        continue;
      for (int i = st; i < et; i++) {
        if (minutes[i]) {
          conflict = true; break;
        }
        else
          minutes[i] = true;
      }
    }
    while (m--) {
      int st, et, ri;
      scanf("%d %d %d", &st, &et, &ri);
      if (conflict)
        continue;
      for (int i = 0; i <= minutes_max; i += ri) {
        for (int j = i + st; j <= minutes_max && j < i + et; j++) {
          if (minutes[j]) {
            conflict = true; break;
          }
          else
            minutes[j] = true;
        }
        if (conflict)
          break;
      }
    }
    puts(((conflict) ? "CONFLICT" : "NO CONFLICT"));
  }
  return 0;
}

UVa 465 - Overflow

Accepted date: 2011-07-23
First verdict date: 2011-07-23
Last verdict date: 2017-01-08
Run Time: 0.000
Ranking (as of 2017-01-14): 1144 out of 3584
Language: C++

/*
  UVa 465 - Overflow

  To build using Visucal Studio 2008:
    cl -EHsc -O2 overflow.cpp
*/

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

int main()
{
  string line;
  while (getline(cin, line)) {
    istringstream iss(line);
    double i, j;
    char op;
    iss >> i >> op >> j;
    double result = (op == '+') ?  i + j : i * j;
    cout << line << endl;
    if (i > numeric_limits<int>::max())
      cout << "first number too big\n";
    if (j > numeric_limits<int>::max())
      cout << "second number too big\n";
    if (result > numeric_limits<int>::max())
      cout << "result too big\n";
  }
  return 0;
}

Thursday, January 12, 2017

UVa 12034 - Race

Accepted date: 2017-01-12
Run Time: 0.000
Ranking (as of 2016-01-12): 54 out of 401
Language: C++

An easy dynamic programming problem.


/*
  UVa 12034 - Race

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

#include <cstdio>

const int n_max = 1000, modulo = 10056;
int combinations[n_max + 1][n_max + 1];
int nr_ways[n_max + 1]; // nr_ways[i] is the number of way the race can finish with i horses

int main()
{
  // calculate the combinations
  for (int i = 0; i <= n_max; i++)
    combinations[i][0] = 1;
  for (int i = 0; i <= n_max; i++)
    combinations[i][i] = 1;
  for (int i = 1; i <= n_max; i++)
    for (int j = 1; j < i; j++)
      combinations[i][j] = (combinations[i - 1][j - 1] + combinations[i - 1][j]) % modulo;
  nr_ways[1] = 1;
  for (int i = 2; i <= n_max; i++) {
    int nr = 1;
    for (int j = 1; j < i; j++) {
      nr += combinations[i][j] * nr_ways[i - j] % modulo;
      nr %= modulo;
    }
    nr_ways[i] = nr;
  }
  int T;
  scanf("%d", &T);
  for (int t = 1; t <= T; t++) {
    int n;
    scanf("%d", &n);
    printf("Case %d: %d\n", t, nr_ways[n]);
  }
  return 0;
}

Wednesday, January 11, 2017

UVa 12238 - Ants Colony

Accepted date: 2017-01-11
Run Time: 0.330
Ranking (as of 2016-01-11): 31 out of 359
Language: C++

For explanation, see Range Minimum Query and Lowest Common Ancestor - topcoder.


/*
  UVa 12238 - Ants Colony

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

#include <algorithm>
#include <vector>
#include <cstdio>
#ifdef __ELAPSED_TIME__
#include <ctime>
#endif
using namespace std;

const int N_max = 100000;

struct edge {
  int v_;
  int weight_;
  edge(int v, int weight) : v_(v), weight_(weight) {}
};

vector<edge> edges[N_max];

const int level_max = 17; // ceil(log2(N_max))
int levels[N_max]; // level (depth) of node i in the tree
long long weights[N_max]; // weights[i] is the total length from the root to i-th node
int parents[N_max]; // parent node of i
int ancestors[N_max][level_max + 1];
  // ancestors[i][j] is the 2^j-th ancestor of node i

void dfs(int u, int parent, int level)
{
  levels[u] = level;
  const vector<edge>& mes = edges[u];
  for (size_t i = 0; i < mes.size(); i++) {
    int v = mes[i].v_, w = mes[i].weight_;
    if (v != parent) {
      parents[v] = u, weights[v] = w + weights[u];
      dfs(v, u, level + 1);
    }
  }
}

void process3(int n)
{
  for (int i = 0 ; i < n; i++) {
    // the first ancestor of every node i is parents[i]
    ancestors[i][0] = parents[i];
    for (int j = 1; 1 << j < n; j++)
      ancestors[i][j] = -1;
  }
  for (int j = 1; 1 << j < n; j++)
    for (int i = 0; i < n; i++)
      if (ancestors[i][j - 1] != -1)
        ancestors[i][j] = ancestors[ancestors[i][j - 1]][j - 1];
}

long long query(int p, int q)
{
  long long w = weights[p] + weights[q];
  //if p is situated on a higher level than q then we swap them
  if (levels[p] < levels[q])
    swap(p, q);
  // we compute the value of [log2(level[p)]
  int log;
  for (log = 1; 1 << log <= levels[p]; log++)
    ;
  log--;
  // we find the ancestor of node p situated on the same level
  // with q using the values in ancestors[][]
  for (int i = log; i >= 0; i--)
    if (levels[p] - (1 << i) >= levels[q])
      p = ancestors[p][i];
  if (p == q)
  return w - weights[p] * 2;
  // we compute LCA(p, q) using the values in ancestors[][]
  for (int i = log; i >= 0;i--)
    if (ancestors[p][i] != -1 && ancestors[p][i] != ancestors[q][i])
      p = ancestors[p][i], q = ancestors[q][i];
  return w - weights[parents[p]] * 2;
}

int main()
{
#ifdef __ELAPSED_TIME__
  clock_t start = clock();
#endif
  while (true) {
    int N;
    scanf("%d", &N);
    if (!N)
      break;
    for (int i = 0; i < N; i++)
      edges[i].clear();
    for (int v = 1; v < N; v++) {
      int u, w;
      scanf("%d %d", &u, &w);
      edges[u].push_back(edge(v, w)), edges[v].push_back(edge(u, w));
    }
    dfs(0, -1, 0);
    process3(N);
    int Q;
    scanf("%d", &Q);
    while (Q--) {
      int s, t;
      scanf("%d %d", &s, &t);
      printf("%lld%c", query(s, t), ((Q) ? ' ' : '\n'));
    }
  }
#ifdef __ELAPSED_TIME__
  fprintf(stderr, "elapsed time = %lf sec.\n",
    static_cast<double>(clock() - start) / CLOCKS_PER_SEC);
#endif
  return 0;
}

Monday, January 9, 2017

UVa 11732 - "strcmp()" Anyone?

Accepted date: 2017-01-09
Run Time: 0.110
Ranking (as of 2016-01-09): 2 out of 369
Language: C++

You can easily see that the below program works for some input cases of small N.


/*
  UVa 11732 - "strcmp()" Anyone?

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

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

const int N_max = 4000, nr_chars_max = 1000;

struct string {
  char s_[nr_chars_max + 1];

  bool operator<(const string& s) const {return strcmp(s_, s.s_) < 0;}
} strings[N_max];

int nr_comparisons[N_max];
  // nr_comparisons[i] is the number of comparisons between strings[i] and strings[i + 1]

int main()
{
  for (int c = 1; ; c++) {
    int N;
    scanf("%d", &N);
    if (!N)
      break;
    for (int i = 0; i < N; i++)
      scanf("%s", strings[i].s_);
    sort(strings, strings + N);
    for (int i = 0; i < N - 1; i++) {
      const char *cs = strings[i].s_, *ns = strings[i + 1].s_;
      int nr = 1;
      for ( ; *cs == *ns; nr++, cs++, ns++) {
        nr++;
        if (!*cs)
          break;
      }
      nr_comparisons[i] = nr;
    }
    long long T = 0;
    for (int i = 0; i < N - 1; i++) {
      int nr = nr_comparisons[i];
      T += nr;
      for (int j = i + 1; j < N - 1; j++) {
        if (nr_comparisons[j] < nr)
          nr = nr_comparisons[j];
        T += nr;
      }
    }
    printf("Case %d: %lld\n", c, T);
  }
  return 0;
}

Tuesday, January 3, 2017

UVa 10823 - Of Circles and Squares

Accepted date: 2017-01-03
Run Time: 0.000
Ranking (as of 2016-01-03): 8 out of 369
Language: C++

In object oriented programming, the vector of object instances would be created and the in method of each object instance would be called with the query point in question.
The below round function is from UVa OJ Board.


/*
  UVa 10823 - Of Circles and Squares

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

#include <cstdio>

const int R_max = 100;

struct object {
  int x_, y_; // center or lower left corner
  int length_; // radius or side length
  int r_, g_, b_;
  virtual int in(int px, int py) const = 0;
    // return porasitive value if (px, py) is inside the object, 
    // 0 if (px, py) is on the boundary of the object
    // negative value if (px, py) is outside of the object
};

struct circle : public object {
  virtual int in(int px, int py) const;
} circles[R_max];

struct square : public object {
  virtual int in(int px, int py) const;
} squares[R_max];

int circle::in(int px, int py) const
{
  return length_ * length_ - (px - x_) * (px - x_) - (py - y_) * (py - y_);
}

int square::in(int px, int py) const
{
  if (px == x_ || px == x_ + length_)
    return (py >= y_ && py <= y_ + length_) ? 0 : -1;
  else if (py == y_ || py == y_ + length_)
    return (px >= x_ && px <= x_ + length_) ? 0 : -1;
  else
    return (px > x_ && px < x_ + length_ && py > y_ && py < y_ + length_) ? 1 : -1;
}

int round(int p, int q)   /* Rounds fraction p/q */
{
  return (p / q) + (((2 * (p % q)) >= q) ? 1 : 0);
}

int main()
{
  int T;
  scanf("%d", &T);
  for (int t = 1; t <= T; t++) {
    int R, P;
    scanf("%d %d", &R, &P);
    int nr_circles = 0, nr_squares = 0;
    while (R--) {
      char type[8];
      scanf("%s", type);
      if (type[0] == 'C') { // "CIRCLE"
        circle& c = circles[nr_circles++];
        scanf("%d %d %d %d %d %d", &c.x_, &c.y_, &c.length_, &c.r_, &c.g_, &c.b_);
      }
      else { // "SQUARE"
        square& s = squares[nr_squares++];
        scanf("%d %d %d %d %d %d", &s.x_, &s.y_, &s.length_, &s.r_, &s.g_, &s.b_);
      }
    }
    printf("Case %d:\n", t);
    while (P--) {
      int px, py;
      scanf("%d %d", &px, &py);
      int nr_objects = 0, r = 0, g = 0, b = 0;
      for (int i = 0; i < nr_circles; i++) {
        const circle& c = circles[i];
        int result = c.in(px, py);
        if (!result) {
          nr_objects = 1;
          r = g = b = 0;
#ifdef DEBUG
          printf("on the boundary of circle: %d %d %d\n", c.x_, c.y_, c.length_);
#endif
          break;
        }
        else if (result > 0) {
          nr_objects++;
          r += c.r_, g += c.g_, b += c.b_;
#ifdef DEBUG
          printf("in the circle: %d %d %d\n", c.x_, c.y_, c.length_);
#endif
        }
      }
      if (nr_objects == 1 && !r && !g && !b) // point is on the boundary of an object
        ;
      else {
        for (int i = 0; i < nr_squares; i++) {
          const square& s = squares[i];
          int result = s.in(px, py);
          if (!result) {
            nr_objects = 1;
            r = g = b = 0;
#ifdef DEBUG
          printf("on the boundary of square: %d %d %d\n", s.x_, s.y_, s.length_);
#endif
            break;
          }
          else if (result > 0) {
            nr_objects++;
            r += s.r_, g += s.g_, b += s.b_;
#ifdef DEBUG
          printf("in the square: %d %d %d\n", s.x_, s.y_, s.length_);
#endif
          }
        }
      }
      if (nr_objects)
        printf("(%d, %d, %d)\n",
          round(r, nr_objects), round(g, nr_objects), round(b, nr_objects));
/*
        printf("(%.0lf, %.0lf, %.0lf)\n", static_cast<double>(r) / nr_objects,
          static_cast<double>(g) / nr_objects, static_cast<double>(b) / nr_objects);
*/
      else
        puts("(255, 255, 255)");
    }
    if (t < T)
      putchar('\n');
  }
  return 0;
}