Monday, May 2, 2016

UVa 11341 - Term Strategy

Accepted date: 2016-05-02
Run Time: 0.000
Ranking (as of 2016-05-02): 87 out of 436
Language: C++

/*
  UVa 11341 - Term Strategy

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

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

const int N_max = 10, M_max = 100, min_grade = 5;
int table[N_max + 1][M_max + 1];
int grades[N_max + 1][M_max + 1];
  // grades[i][j] is max. of the total grade up to i-th courses 
  // with j hours spent for preparation

int main()
{
  int T;
  scanf("%d", &T);
  while (T--) {
    int N, M, m = 0;
    scanf("%d %d", &N, &M);
    for (int i = 1; i <= N; i++)
      for (int j = 1, k = 1; j <= M; j++) {
        scanf("%d", &table[i][k]);
        if (table[i][k] >= min_grade)
          k++;
        else
          m++;
      }
    M -= m;
    if (M < N) {
      puts("Peter, you shouldn't have played billiard that much.");
      continue;
    }
    for (int j = 1; j <= M; j++)
      grades[1][j] = table[1][j];
    for (int i = 2; i <= N; i++)
      for (int j = i; j <= M; j++) {
        int g = 0;
        for (int k = 1; k < j; k++)
          g = max(g, grades[i - 1][k] + table[i][j - k]);
        grades[i][j] = g;
      }
    printf("Maximal possible average mark - %.2lf.\n",
      static_cast<double>(grades[N][M]) / N + 1.0e-9);
      // Without 1.0e-9, you will receive the verdict Wrong Answer.
  }
  return 0;
}

Saturday, April 30, 2016

UVa 11960 - Divisor Game

Accepted date: 2016-04-30
Run Time: 0.040
Ranking (as of 2016-04-29): 32 out of 462
Language: C++

/*
  UVa 11960 - Divisor Game

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

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

const int N_max = 1000000;
int nr_of_divisors[N_max + 1], most_divisors[N_max + 1];

int main()
{
  for (int i = 1; i <= N_max; i++)
    for (int j = i; j <= N_max; j += i)
      nr_of_divisors[j]++;
  for (int i = 1, most = 0, most_i = 0; i <= N_max; i++) {
    if (most <= nr_of_divisors[i]) {
      most = nr_of_divisors[i];
      most_i = i;
    }
    most_divisors[i] = most_i;
  }
  int T;
  scanf("%d", &T);
  while (T--) {
    int n;
    scanf("%d", &n);
    printf("%d\n", most_divisors[n]);
  }
  return 0;
}

Friday, April 29, 2016

UVa 1644 - Prime Gap

Accepted date: 2016-04-29
Run Time: 0.000
Ranking (as of 2016-04-29): 9 out of 446
Language: C++

/*
  UVa 1644 - Prime Gap

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

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

const int n_max = 1299709, nr_primes = 100000;
bool not_primes[n_max + 1]; // not_primes[i] is true if i is not a prime
int primes[nr_primes];

void sieve_of_eratosthenes()
{
  not_primes[0] = not_primes[1] = true;
  for (int i = 2, e = static_cast<int>(sqrt(static_cast<double>(n_max))); i <= e; i++)
    if (!not_primes[i]) {
      for (int j = i * i; j <= n_max; j += i)
        not_primes[j] = true;
    }
}

int main()
{
  sieve_of_eratosthenes();
  for (int i = 2, j = 0; i <= n_max; i++)
    if (!not_primes[i])
      primes[j++] = i;
  while (true) {
    int n;
    scanf("%d", &n);
    if (!n)
      break;
    int gap = 0;
    if (not_primes[n]) {
      int i = upper_bound(primes, primes + nr_primes, n) - primes;
      gap = primes[i] - primes[i - 1];
    }
    printf("%d\n", gap);
  }
  return 0;
}

Thursday, April 28, 2016

UVa 11513 - 9 Puzzle

Accepted date: 2016-04-28
Run Time: 0.270
Ranking (as of 2016-04-28): 29 out of 471
Language: C++

/*
  UVa 11513 - 9 Puzzle

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

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

const int nr_squares = 9;
const int nr_paths_max = 362880; // 9!

enum {m_h1, m_h2, m_h3, m_v1, m_v2, m_v3};
const int nr_moves = m_v3 - m_h1 + 1;
const char* original_configuration = "123456789";
const char *moves[] = {"H1", "H2", "H3", "V1", "V2", "V3"};

struct path {
  char squares_[nr_squares];
  int next_;
  int move_;
  int s_;
} paths[nr_paths_max];

int compare_path(const void* i, const void* j)
{
  const path *pi = reinterpret_cast<const path*>(i), *pj = reinterpret_cast<const path*>(j);
  return strcmp(pi->squares_, pj->squares_);
}

int main()
{
#ifdef __ELAPSED_TIME__
  clock_t start = clock();
#endif
  char s[nr_squares + 1];
  strcpy(s, original_configuration);
  int nr_paths = 0;
  do {
    strcpy(paths[nr_paths].squares_, s);
    nr_paths++;
  } while (next_permutation(s, s + nr_squares));
#ifdef DEBUG
  printf("%d\n", nr_paths);
#endif
  // starting from the original configuration, mark the reachables configurations 
  // by moving in the reverse directions
  path p;
  strcpy(p.squares_, original_configuration);
  paths[0].next_ = 0, paths[0].s_ = 0;
  for (int i = 1; i < nr_paths_max; i++)
    paths[i].next_ = -1;
  queue<int> q;
  q.push(0);
  while (!q.empty()) {
    int pi = q.front();
    q.pop();
#ifdef DEBUG
//    printf("%d: %s %d\n", pi, paths[pi].squares_, paths[pi].next_);
#endif
    int ns = paths[pi].s_ + 1;
    for (int i = 0; i < nr_moves; i++) {
      int j;
      char c;
      path np;
      strcpy(np.squares_, paths[pi].squares_);
      if (i < m_v1) { // horizontal left moves
        j = i * 3;
        c = np.squares_[j], np.squares_[j] = np.squares_[j + 1],
          np.squares_[j + 1] = np.squares_[j + 2], np.squares_[j + 2] = c;
      }
      else { // vertical down moves
        j = i - m_v1;
        c = np.squares_[6 + j], np.squares_[6 + j] = np.squares_[3 + j],
          np.squares_[3 + j] = np.squares_[j], np.squares_[j] = c;
      }
      int npi = reinterpret_cast<path*>(bsearch (&np, paths, nr_paths_max, sizeof(path), compare_path)) - paths;
      if (paths[npi].next_ == -1) {
#ifdef DEBUG
//        printf("  %d: %s\n", npi, paths[npi].squares_);
#endif
        paths[npi].next_ = pi, paths[npi].move_ = i, paths[npi].s_ = ns;
        q.push(npi);
      }
    }
  }
  while (true) {
    int n, i = 0;
    scanf("%d", &n);
    if (!n)
      break;
    p.squares_[i++] = n + '0';
    for ( ; i < nr_squares; i++) {
      scanf("%d", &n);
      p.squares_[i] = n + '0';
    }
    int pi = reinterpret_cast<path*>(bsearch (&p, paths, nr_paths_max, sizeof(path), compare_path)) - paths;
    if (paths[pi].next_ != -1) {
      printf(((pi) ? "%d " : "%d"), paths[pi].s_);
      for ( ; pi; pi = paths[pi].next_)
        printf("%s", moves[paths[pi].move_]);
      putchar('\n');
    }
    else
      puts("Not solvable");
  }
#ifdef __ELAPSED_TIME__
  fprintf(stderr, "elapsed time = %lf sec.\n",
    static_cast<double>(clock() - start) / CLOCKS_PER_SEC);
#endif
  return 0;
}

Monday, April 25, 2016

UVa 10097 - The Color Game

Accepted date: 2016-04-25
Run Time: 0.030
Ranking (as of 2016-04-25): 3 out of 479
Language: C++

/*
  UVa 10097 - The Color Game

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

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

const int N_max = 100;

int matrix[N_max + 1][N_max + 1], visited[N_max + 1][N_max + 1];

int main()
{
  for (int g = 1; ; g++) {
    int N;
    scanf("%d", &N);
    if (!N)
      break;
    for (int i = 1; i <= N; i++)
      for (int j= 1; j <= N; j++) {
        int k;
        scanf("%d", &k);
        matrix[i][j] = k;
        visited[i][j] = -1;
      }
    int N1, N2, N3;
    scanf("%d %d %d", &N1, &N2, &N3);
    int min_moves = -1;
    queue< pair<int, int> > q;
    visited[N1][N2] = 0;
    q.push(make_pair(N1, N2));
    while (!q.empty()) {
      pair<int, int> p = q.front();
      q.pop();
      N1 = p.first, N2 = p.second;
      int m = visited[N1][N2];
#ifdef DEBUG
      printf("%d %d %d\n", N1, N2, m);
#endif
      if (N1 == N3 || N2 == N3) {
        min_moves = m;
        break;
      }
      if (N1 != N3) {
        if (matrix[N1][N2] && visited[matrix[N1][N2]][N2] == -1) {
#ifdef DEBUG
          printf("  %d %d %d\n", matrix[N1][N2], N2, m + 1);
#endif
          visited[matrix[N1][N2]][N2] = m + 1;
          q.push(make_pair(matrix[N1][N2], N2));
        }
      }
      if (N2 != N3) {
        if (matrix[N2][N1] && visited[matrix[N2][N1]][N1] == -1) {
#ifdef DEBUG
          printf("    %d %d %d\n", matrix[N2][N1], N1, m + 1);
#endif
          visited[matrix[N2][N1]][N1] = m + 1;
          q.push(make_pair(matrix[N2][N1], N1));
        }
      }
    }
    printf("Game #%d\n", g);
    if (min_moves != -1)
      printf("Minimum Number of Moves = %d\n\n", min_moves);
    else
      printf("Destination is Not Reachable !\n\n");
  }
  return 0;
}

Sunday, April 24, 2016

UVa 10269 - Adventure of Super Mario

Accepted date: 2016-04-24
Run Time: 0.000
Ranking (as of 2016-04-24): 6 out of 642
Language: C++

/*
  UVa 10269 - Adventure of Super Mario

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

#include <algorithm>
#include <vector>
#include <utility>
#include <queue>
#include <set>
#include <limits>
#include <cstdio>
#include <cstring>
using namespace std;

const int A_max = 50, B_max = 50, n_max = A_max + B_max, L_max = 500, K_max = 10;

struct edge {
  int v_;
  int w_;
  edge(int v, int w) : v_(v), w_(w) {}
};

int matrix[n_max + 1][n_max + 1];
bool visited[n_max + 1], dvisited[n_max + 1][K_max + 1];
vector<edge> edges[n_max + 1];
int distances[n_max + 1][K_max + 1];
  // distances[i][j] is the min. time to vertex i using super-runs j times

struct distance_comparator {
  bool operator() (const pair<int, int>& i, const pair<int, int>& j) const
  {
    int di = distances[i.first][i.second], dj = distances[j.first][j.second];
    if (di != dj)
      return di < dj;
    return (i.second != j.second) ? i.second < j.second : i.first < j.first;
  }
};

int main()
{
  int T;
  scanf("%d", &T);
  while (T--) {
    int A, B, M, L, K;
    scanf("%d %d %d %d %d", &A, &B, &M, &L, &K);
    int n = A + B;
    for (int i = 1; i <= n; i++) {
      edges[i].clear();
      for (int j = 1; j <= n; j++)
        matrix[i][j] = numeric_limits<int>::max();
      for (int j = 0; j <= K; j++) {
        dvisited[i][j] = false;
        distances[i][j] = numeric_limits<int>::max();
      }
    }
    while (M--) {
      int Xi, Yi, Li;
      scanf("%d %d %d", &Xi, &Yi, &Li);
      matrix[Xi][Yi] = matrix[Yi][Xi] = Li;
      edges[Xi].push_back(edge(Yi, Li));
      edges[Yi].push_back(edge(Xi, Li));
    }

    // apply the Floyd-Warshall algorithm
    for (int k = 1; k <= A; k++)
      for (int i = 1; i <= n; i++)
        if (matrix[i][k] != numeric_limits<int>::max())
          for (int j = 1; j <= n; j++)
          if (matrix[k][j] != numeric_limits<int>::max())
            matrix[i][j] = min(matrix[i][j], matrix[i][k] + matrix[k][j]);

    // add the edges where super-running can be used
    for (int i = 1; i <= n - 1; i++)
      for (int j = i + 1; j <= n; j++)
        if (matrix[i][j] <= L) {
#ifdef DEBUG
          printf("s %d %d %d\n", i, j, matrix[i][j]);
#endif
          edges[i].push_back(edge(j, 0));
          edges[j].push_back(edge(i, 0));
        }

    // apply the Dijkstra's shortest path algorithm
    set<pair<int, int>, distance_comparator> pq; // priority queue
    distances[n][0] = 0;
    pq.insert(make_pair(n, 0));
    int min_t = numeric_limits<int>::max();
    while(!pq.empty()) {
      pair<int, int> p = *pq.begin();
      pq.erase(pq.begin());
      int u = p.first, k = p.second, t = distances[u][k];
      dvisited[u][k] = true;
#ifdef DEBUG
      printf("%d %d %d\n", u, k, t);
#endif
      if (u == 1) {
        min_t = t;
        break;
      }
      const vector<edge>& es = edges[u];
      for (size_t i = 0, j = es.size(); i < j; i++) {
        int v = es[i].v_, w = es[i].w_;
        if (w && !dvisited[v][k] && t + w < distances[v][k]) {
          // a walk edge
          pair<int, int> q = make_pair(v, k);
          pq.erase(q);
          distances[v][k] = t + w;
#ifdef DEBUG
          printf("  %d %d %d\n", v, k, distances[v][k]);
#endif
          pq.insert(q);
        }
        if (!w && k < K && !dvisited[v][k + 1] && t < distances[v][k + 1]) {
          // a super-running edge
          pair<int, int> q = make_pair(v, k + 1);
          pq.erase(q);
          distances[v][k + 1] = t;
#ifdef DEBUG
          printf("  %d %d %d\n", v, k + 1, distances[v][k + 1]);
#endif
          pq.insert(q);
        }
      }
    }
    printf("%d\n", min_t);
  }
  return 0;
}

Saturday, April 23, 2016

UVa 11635 - Hotel booking

Accepted date: 2016-04-23
Run Time: 0.430
Ranking (as of 2016-04-23): 23 out of 464
Language: C++

/*
  UVa 11635 - Hotel booking

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

#include <vector>
#include <set>
#include <limits>
#include <cstdio>
using namespace std;

const int n_max = 10000, h_max = 100, minutes_max = 10 * 60;

struct edge {
  int v_;
  int w_;
  edge(int v, int w) : v_(v), w_(w) {}
};

bool hotels[n_max + 1], visited[n_max + 1][h_max + 1];
vector<edge> edges[n_max + 1];

struct distance_comparator {
  vector< vector<int> >& distances_;

  distance_comparator(vector< vector<int> >& distances) : distances_(distances) {}
  bool operator() (const pair<int, int>& i, const pair<int, int>& j) const
  {
    if (i.second != j.second)
      return i.second < j.second;
    int di = distances_[i.first][i.second], dj = distances_[j.first][j.second];
    return (di != dj) ? di < dj : i.first < j.first;
  }
};

int main()
{
  while (true) {
    int n;
    scanf("%d", &n);
    if (!n)
      break;
    int h;
    scanf("%d", &h);
    for (int i = 1; i <= n; i++) {
      hotels[i] = false;
      edges[i].clear();
      for (int j = 0; j <= h; j++)
        visited[i][j] = false;
    }
    for (int i = 0; i < h; i++) {
      int c;
      scanf("%d", &c);
      hotels[c] = true;
    }
    int m;
    scanf("%d", &m);
    while (m--) {
      int a, b, t;
      scanf("%d %d %d", &a, &b, &t);
      edges[a].push_back(edge(b, t));
      edges[b].push_back(edge(a, t));
    }
    // apply the Dijkstra's shortest path algorithm
    vector< vector<int> > distances(n + 1, vector<int>(h + 1, numeric_limits<int>::max()));
    set<pair<int, int>, distance_comparator> pq(distances); // priority queue
    distances[1][0] = 0;
    pq.insert(make_pair(1, 0));
    int min_d = -1;
    while(!pq.empty()) {
      pair<int, int> p = *pq.begin();
      pq.erase(pq.begin());
      int u = p.first, d = p.second, t = distances[u][d];
      visited[u][d] = true;
#ifdef DEBUG
      printf("%d %d %d\n", u, d, t);
#endif
      if (u == n) {
        min_d = d;
        break;
      }
      const vector<edge>& es = edges[u];
      for (size_t i = 0, j = es.size(); i < j; i++) {
        int v = es[i].v_, w = es[i].w_;
        if (t + w <= minutes_max &&
          !visited[v][d] && t + w < distances[v][d]) {
          pair<int, int> q = make_pair(v, d);
          pq.erase(q);
          distances[v][d] = t + w;
#ifdef DEBUG
          printf("  %d %d %d\n", v, d, distances[v][d]);
#endif
          pq.insert(q);
        }
        if (hotels[u] && d < h && w <= minutes_max &&
          !visited[v][d + 1] && w < distances[v][d + 1]) {
          pair<int, int> q = make_pair(v, d + 1);
          pq.erase(q);
          distances[v][d + 1] = w;
#ifdef DEBUG
          printf("  %d %d %d\n", v, d + 1, distances[v][d + 1]);
#endif
          pq.insert(q);
        }
      }
    }
    printf("%d\n", min_d);
  }
  return 0;
}