Saturday, June 25, 2016

UVa 11957 - Checkers

Accepted date: 2016-06-25
Run Time: 0.000
Ranking (as of 2016-06-25): 23 out of 408
Language: C++

/*
  UVa 11957 - Checkers

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

#include <cstdio>

const int N_max = 100, divisor = 1000007;

char board[N_max][N_max + 1];
int N, nr_paths[N_max][N_max];
  // nr_paths[y][x] is the number of paths to the cell (x, y)

int from_left(int y, int x, bool jumped)
{
  y++, x--;
  if (y < N && x >= 0) {
    if (board[y][x] != 'B')
      return nr_paths[y][x];
    else
      return (jumped) ? 0 : from_left(y, x, true);
  }
  else
    return 0;
}

int from_right(int y, int x, bool jumped)
{
  y++, x++;
  if (y < N && x < N) {
    if (board[y][x] != 'B')
      return nr_paths[y][x];
    else
      return (jumped) ? 0: from_right(y, x, true);
  }
  else
    return 0;
}

int main()
{
  int T;
  scanf("%d", &T);
  for (int t = 1; t <= T; t++) {
    scanf("%d", &N);
    int sy, sx;
    for (int y = 0; y < N; y++) {
      scanf("%s", board[y]);
      for (int x = 0; x < N; x++)
        if (board[y][x] == 'W')
          sy = y, sx = x;
    }
    for (int y = 0; y < N; y++)
      for (int x = 0; x < N; x++)
        nr_paths[y][x] = 0;
    nr_paths[sy][sx] = 1;
    for (int y = sy - 1; y >= 0; y--)
      for (int x = 0; x < N; x++)
        if (board[y][x] != 'B')
          nr_paths[y][x] = (from_left(y, x, false) + from_right(y, x, false)) % divisor;
    int nr = 0;
    for (int x  = 0; x < N; x++) {
      nr += nr_paths[0][x];
      nr %= divisor;
    }
    printf("Case %d: %d\n", t, nr);
  }
  return 0;
}

Monday, June 20, 2016

UVa 12366 - King's Poker

Accepted date: 2016-06-20
Run Time: 0.000
Ranking (as of 2016-06-20): 20 out of 407
Language: C++

/*
  UVa 12366 - King's Poker

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

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

int main()
{
  while (true) {
    int A, B, C;
    scanf("%d %d %d", &A, &B, &C);
    if (!A)
      break;
    // sort A, B, and C in ascending order
    if (A > B)
      swap(A, B);
    if (B > C)
      swap(B, C);
    if (A > B)
      swap(A, B);
    if (A == B && B == C) { // set
      if (A == 13)
        A = 0; // impossible
      else
        A = B = C = ++A;
    }
    else if (A == B) { // pair
      if (C == 13)
        A = 1, B = C = ++B;
      else
        C++;
    }
    else if (B == C) { // pair
      if (A == 12 && B == 13)
        A = B = C = 1;
      else if (A + 1 == B)
        A = C, C = B + 1;
      else
        A++;
    }
    else { // no-pair
      A = B = 1, C = 2;
    }
    if (A)
      printf("%d %d %d\n", A, B, C);
    else
      puts("*");
  }
  return 0;
}

Sunday, June 19, 2016

UVa 10406 - Cutting tabletops

Accepted date: 2016-06-19
Run Time: 0.000
Ranking (as of 2016-06-19): 115 out of 411
Language: C++

/*
  UVa 10406 - Cutting tabletops

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

#include <algorithm>
#include <vector>
#include <iterator>
#include <limits>
#include <cstdio>
#include <cmath>
using namespace std;

const double epsilon = numeric_limits<float>::epsilon();

struct point {
  double x_, y_;

  point() {}
  point(double x, double y) : x_(x), y_(y) {}
  point(const point &p) : x_(p.x_), y_(p.y_) {}
  bool operator==(const point& p) const {
    return fabs(x_ - p.x_) <= epsilon && fabs(y_ - p.y_) <= epsilon;
  }
};

double euclidean_distance(const point& a, const point& b)
{
  double dx = a.x_ - b.x_, dy = a.y_ - b.y_;
  return sqrt(dx * dx + dy * dy);
}

double cross_product(const point& o, const point& a, const point& b)
{
  return (a.x_ - o.x_) * (b.y_ - o.y_) - (b.x_ - o.x_) * (a.y_ - o.y_);
}

void get_cut_points(double d, const point& p, const point& q, point& cp, point& cq)
{
  double x = p.y_ - q.y_, y = q.x_ - p.x_, t = d / euclidean_distance(p, q);
  cp.x_ = p.x_ + x * t; cp.y_ = p.y_ + y * t;
    // cp(p.x_ + d * cos(theta), p.y_ + d * sin(theta)), 
    // cos(theta) = x / distance(p, q), sin(theta) = y / distance(p, q)
  cq.x_ = q.x_ + x * t; cq.y_ = q.y_ + y * t;
}

point get_intersect_points(const point& p1, const point& p2, const point& q1, const point& q2)
{
  double hq1 = cross_product(p1, p2, q1), hq2 = cross_product(p2, p1, q2);
    // fabs(hq1) is the distance between q1 and the vector p1 -> p2,
    // fabs(hq2) is the distance between q2 and the vector p2 -> p1
  double hq = hq1 + hq2;
    return point((q1.x_ * hq2 + q2.x_ * hq1) / hq, (q1.y_ * hq2 + q2.y_ * hq1) / hq);
}

double polygon_area(int n, const vector<point>& polygon)
{
  double area = 0.0;
  for (int i = 0; i < n; i++)
    area += polygon[i].x_ * polygon[(i + 1) % n].y_ - polygon[(i + 1) % n].x_ * polygon[i].y_;
  return area / 2.0;
}

#ifdef DEBUG
void print_polygon(int n, const vector<point>& polygon)
{
  for (int i = 0; i < n; i++)
    printf("(%.3lf, %.3lf)%c", polygon[i].x_, polygon[i].y_, ((i < n - 1) ? ' ' : '\n'));
}
#endif

int main()
{
  while (true) {
    double d;
    int n;
    scanf("%lf %d", &d, &n);
    if (d == 0.0 && n == 0)
      break;
    vector<point> points(n);
    for (int i = n - 1; i >= 0; i--)
      scanf("%lf %lf", &points[i].x_, &points[i].y_);
    vector<point> cpoints(n * 2);
    for (int i = 0; i < n; i++)
      get_cut_points(d, points[i], points[(i + 1) % n], cpoints[i * 2], cpoints[i * 2 + 1]);
#ifdef DEBUG
    print_polygon(n * 2, cpoints);
#endif
    for (int i = 0; i < n; i++)
      points[i] = get_intersect_points(cpoints[i * 2], cpoints[i * 2 + 1],
        cpoints[(i * 2 + 2) % (n * 2)], cpoints[(i * 2 + 3) % (n * 2)]);
#ifdef DEBUG
    print_polygon(n, points);
#endif
    printf("%.3lf\n", polygon_area(n, points));
  }
  return 0;
}

Saturday, June 18, 2016

UVa 10574 - Counting Rectangles

Accepted date: 2016-06-18
Run Time: 0.120
Ranking (as of 2016-06-18): 8 out of 412
Language: C++11

/*
  UVa 10574 - Counting Rectangles

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

#include <algorithm>
#include <iterator>
#include <map>
#include <vector>
#include <cstdio>
using namespace std;

int main()
{
  int t;
  scanf("%d", &t);
  for (int cn = 1; cn <= t; cn++) {
    int n;
    scanf("%d", &n);
    map< int, vector<int> > points;
      // points[i] is the set of y coordinates of points whose x coordinate is i
    for (int i = 0; i < n; i++) {
      int x, y;
      scanf("%d %d", &x, &y);
      pair<map<int, vector<int> >::iterator, bool>
        result = points.insert(make_pair(x, vector<int>()));
      result.first->second.push_back(y);
    }
    for (map<int, vector<int> >::iterator xi = points.begin(); xi != points.end(); ) {
      if (xi->second.size() < 2)
        points.erase(xi++);
      else {
        sort(xi->second.begin(), xi->second.end());
        ++xi;
      }
    }
    long long nr_rectangles = 0;
    for (map<int, vector<int> >::const_iterator xl = points.begin(), xe = points.end();
      xl != xe; ++xl)
      for (map<int, vector<int> >::const_iterator xr = next(xl); xr != xe; ++xr) {
        const vector<int>& yls = xl->second;
        const vector<int>& yrs = xr->second;
        long long nr_ys = 0;
        for (size_t li = 0, le = yls.size(), ri = 0, re = yrs.size();
          li < le && ri < re; ) {
          if (yls[li] < yrs[ri])
            li++;
          else if (yls[li] > yrs[ri])
            ri++;
          else {
            nr_ys++;
            li++, ri++;
          }
        }
        if (nr_ys > 1)
          nr_rectangles += nr_ys * (nr_ys - 1) / 2;
      }
    printf("Case %d: %d\n", cn, nr_rectangles);
  }
  return 0;
}

Thursday, June 16, 2016

UVa 10668 - Expanding Rods

Accepted date: 2016-06-16
Run Time: 0.000
Ranking (as of 2016-06-16): 190 out of 490
Language: C++

/*
  UVa 10668 - Expanding Rods

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

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

int main()
{
  const double pi = 2.0 * acos(0.0), epsilon = numeric_limits<double>::epsilon();
  while (true) {
    double l, n, c;
    scanf("%lf %lf %lf", &l, &n, &c);
    if (l < 0.0 && n < 0.0 && c < 0.0)
      break;
    if (l < epsilon || n < epsilon || c < epsilon) {
      printf("%.3lf\n", 0.0);
      continue;
    }
    double nl = (1.0 + n * c) * l, mid;
    for (double low = 0.0, high = pi / 2.0; low - high < epsilon; ) {
      mid = (low + high) / 2.0;
#ifdef DEBUG
      printf("%.15lf %.15lf %.15lf\n", low, mid, high);
#endif
      double result = nl / mid - l / sin(mid);
      if (result > epsilon)
        low = mid;
      else if (result < -epsilon)
        high = mid;
      else
        break;
    }
    double r = nl / (mid * 2.0), d = r * (1.0 - cos(mid));
    printf("%.3lf\n", d);
  }
  return 0;
}

Tuesday, June 14, 2016

UVa 11374 - Airport Express

Accepted date: 2016-06-14
Run Time: 0.000
Ranking (as of 2016-06-14): 42 out of 412
Language: C++

/*
  UVa 11374 - Airport Express

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

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

const int N_max = 500;

struct edge {
  int v_;
  int w_;
  int commercial_; // 1 for Commercial-Xpress, 0 for Economy-Xpress
  edge(int v, int w, int commercial) : v_(v), w_(w), commercial_(commercial) {}
};

vector<edge> edges[N_max + 1];
bool dvisited[N_max + 1][2];
int distances[N_max + 1][2];
  // distances[i][0/1] is the min. time to vertex i using Commercial-Xpress (1) or not (0)

struct path {
  int u_, commercial_;
} paths[N_max + 1][2];

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;
  }
};

void print_path(int u, int c, int& cu)
{
  if (paths[u][c].u_ == -1)
    printf("%d", u);
  else {
    if (c && !paths[u][c].commercial_)
      cu = paths[u][c].u_;
    print_path(paths[u][c].u_, paths[u][c].commercial_, cu);
    printf(" %d", u);
  }
}

int main()
{
  int N, S, E;
  bool printed = false;
  while (scanf("%d %d %d", &N, &S, &E) != EOF) {
    if (printed)
      putchar('\n');
    else
      printed = true;
    for (int i = 1; i <= N; i++) {
      edges[i].clear();
      dvisited[i][0] = dvisited[i][1] = false;
      distances[i][0] = distances[i][1] = numeric_limits<int>::max();
    }
    int M;
    scanf("%d", &M);
    while (M--) {
      int X, Y, Z;
      scanf("%d %d %d", &X, &Y, &Z);
      edges[X].push_back(edge(Y, Z, 0));
      edges[Y].push_back(edge(X, Z, 0));
    }
    int K;
    scanf("%d", &K);
    while (K--) {
      int X, Y, Z;
      scanf("%d %d %d", &X, &Y, &Z);
      edges[X].push_back(edge(Y, Z, 1));
      edges[Y].push_back(edge(X, Z, 1));
    }
    // apply the Dijkstra's shortest path algorithm
    set<pair<int, int>, distance_comparator> pq; // priority queue
    distances[S][0] = 0;
    paths[S][0].u_ = -1;
    pq.insert(make_pair(S, 0));
    int min_t, min_c;
    while(!pq.empty()) {
      pair<int, int> p = *pq.begin();
      pq.erase(pq.begin());
      int u = p.first, cc = p.second, t = distances[u][cc];
      dvisited[u][cc] = true;
#ifdef DEBUG
      printf("[%d][%d]: %d\n", u, cc, t);
#endif
      if (u == E) {
        min_t = t, min_c = cc;
        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_, c = es[i].commercial_;
        if (c) {
          if (!cc && !dvisited[v][1] && t + w < distances[v][1]) {
            pair<int, int> q = make_pair(v, 1);
            pq.erase(q);
            distances[v][1] = t + w, paths[v][1].u_ = u, paths[v][1].commercial_ = cc;
#ifdef DEBUG
            printf("  [%d][1]: %d\n", v, distances[v][1]);
#endif
            pq.insert(q);
          }
        }
        else {
          if (!dvisited[v][cc] && t + w < distances[v][cc]) {
            pair<int, int> q = make_pair(v, cc);
            pq.erase(q);
            distances[v][cc] = t + w, paths[v][cc].u_ = u, paths[v][cc].commercial_ = cc;
#ifdef DEBUG
            printf("  [%d][%d]: %d\n", v, cc, distances[v][cc]);
#endif
            pq.insert(q);
          }
        }
      }
    }
    int cu = -1;
    print_path(E, min_c, cu);
    if (cu != -1)
      printf("\n%d\n", cu);
    else
      printf("\nTicket Not Used\n");
    printf("%d\n", min_t);
  }
  return 0;
}


Sunday, June 12, 2016

UVa 866 - Intersecting Line Segments

Accepted date: 2016-06-12
Run Time: 0.000
Ranking (as of 2016-06-12): 181 out of 631
Language: C++

/*
  UVa 866 - Intersecting Line Segments

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

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

struct point{
  int x, y;
};

struct segment{
  point s, e;
};

inline bool in_range(int l, int u, int n)
{
  return n >= l && n <= u;
}

int direction(const point& p1, const point& p2, const point& p3)
{
  return (p1.x - p2.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p2.y);
}

bool on_segment(const point& p1, const point& p2, const point& p3)
{
  return in_range(min(p1.x, p2.x), max(p1.x, p2.x), p3.x) &&
    in_range(min(p1.y, p2.y), max(p1.y, p2.y), p3.y);
}

bool segment_intersect(const point& p1, const point& p2, const point& p3, const point& p4)
{
  int d1 = direction(p3, p4, p1), d2 = direction(p3, p4, p2),
    d3 = direction(p1, p2, p3), d4 = direction(p1, p2, p4);
  if((d1 > 0 && d2 < 0 || d1 < 0 && d2 > 0) && (d3 > 0 && d4 < 0 || d3 < 0 && d4 > 0))
    return true;
/*
From the problem descrition:
  It is assumed, as a simplification, 
  that no coincidences may occur between coordinates of singular 
  points (intersections or end points).
*/
/*
  if (d1 == 0 && on_segment(p3, p4, p1))
    return true;
  if (d2 == 0 && on_segment(p3, p4, p2))
    return true;
  if (d3 == 0 && on_segment(p1, p2, p3))
    return true;
  if (d4 == 0 && on_segment(p1, p2, p4))
    return true;
*/
  return false;
}

int main()
{
  int nr_cases;
  scanf("%d", &nr_cases);
  while (nr_cases--) {
    int N;
    scanf("%d", &N);
    vector<segment> segments(N);
    for (int i = 0; i < N; i++)
      scanf("%d %d %d %d",
        &segments[i].s.x, &segments[i].s.y, &segments[i].e.x, &segments[i].e.y);
    int nr_segments = N;
    for (int i = 0; i < N - 1; i++)
      for (int j = i + 1; j < N; j++)
        if (segment_intersect(segments[i].s, segments[i].e, segments[j].s, segments[j].e))
          nr_segments += 2;
    printf("%d\n", nr_segments);
    if (nr_cases)
      putchar('\n');
  }
  return 0;
}