Google Code Jam 1A

Problem A - Rotate の解答例

普通にやるんだったら右・下・右下・左下の4方向についてdx, dyを作ってやるのが楽だと思う.計算時間のオーダーどっちも O(N2K) だし,N,K≦50だし.方法が面白いので敢えてビット操作.以前見た情報処理学会会誌(2008年12月号/Vol.49 No.12)掲載の田浦先生版N-Queenの記憶を導きつつ.

#include <iostream>
#include <string>
#include <vector>
using namespace std;
typedef unsigned long long uint64;

bool check(const int K, const vector<string>& str, const char c)
{
  const int N = str.size();
  vector<uint64> bit;

  // Convert & partial check
  for( int i = 0 ; i < N ; ++i ) {
    uint64 row = 0;
    for( int j = 0 ; j < N ; ++j ) {
      if( str[i][j] == '.' ) { continue; }
      row <<= 1;
      if( str[i][j] == c ) { row |= 1; }
    }
    bit.push_back(row);

    // Check HoRizontal
    uint64 hr = row;
    for( int j = 1 ; j < K ; ++j ) { hr = (hr << 1) & row; }
    if( hr ) { return true; }
  }

  // Check Vertically, Left-down diagonary, Right-down diagonary
  for( int i = 0 ; i <= N - K ; ++i ) {
    uint64 v, l, r;
    v = l = r = bit[i];
    for( int j = i + 1 ; j < i + K ; ++j ) {
      v &= bit[j];
      l = (l << 1) & bit[j];
      r = (r >> 1) & bit[j];
    }
    if( v | l | r ) { return true; }
  }

  return false;
}

string solve()
{
  int N, K;
  cin >> N >> K;
  vector<string> board(N);
  for( int i = 0 ; i < N ; ++i ) cin >> board[i];

  bool red  = check(K, board, 'R');
  bool blue = check(K, board, 'B');
  
  if( red && blue ) return string("Both");
  if( red ) return string("Red");
  if( blue ) return string("Blue");
  return string("Neither");
}

int main(void)
{
  int T;
  cin >> T;
  for( int t = 1 ; t <= T ; ++t ) {
    cerr << "Case #" << t << "\n";
    cout << "Case #" << t << ": " << solve() << "\n";
  }
}

Problem B - Make it Smooth の解答例

1000*256 は何か理由があるわけじゃなくて,単純に大きな数です.十分大きければいいんだけど,INT_MAX とか使うとその後の加算でオーバーフローするので止めました.

#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

int table[102][256];
int D, I, M, N;
int a[101];

void makeTable(void)
{
  for( int i = 0 ; i < 256 ; ++i ) {
    table[0][i] = 0;
  }

  for( int len = 0 ; len < N ; ++len ) {
    for( int last = 0 ; last < 256 ; ++last ) {
      // Try deleting
      int min = table[len][last] + D;

      // Try all values for the previous pixel value
      for( int i = 0 ; i < 256 ; ++i ) {
        int pre = table[len][i];
        int mov = abs(last - a[len]);
        int ins = (M) ? (((abs(last - i) - 1) / M) * I) : ( last == i ) ? 0 : (1000 * 256);
        ins = (ins < 0) ? 0 : ins;
        min = ( min < pre + mov + ins ) ? min : (pre + mov + ins);
      }
      table[len+1][last] = min;
    }
  }
}

int solve(void)
{
  // Input
  cin >> D >> I >> M >> N;
  for( int i = 0 ; i < N ; ++i ) { cin >> a[i]; }

  // Make information
  makeTable();

  // Search minimum
  int min = table[N][0];
  for( int i = 1 ; i < 256 ; ++i ) {
    min = (min < table[N][i]) ? min : table[N][i];
  }
  return min;
}

int main(void)
{
  int T;
  cin >> T;
  for( int t = 1 ; t <= T ; ++t ) {
    cerr << "Case #" << t << "\n";
    cout << "Case #" << t << ": " << solve() << "\n";
  }
  return 0;
}

Problem C - Number Game の解答例

Analyticsにある通りの計算をしただけ.あと対称性からA≧φBだけじゃなくてφA≦Bもカウントするべし.

#include <iostream>
#include <cmath>
using namespace std;
typedef long long int64;

const double GOLD1 = (1 + sqrt(5.0)) * .5;
const double GOLD2 = 1.0 / GOLD1;

int64 solve(void)
{
  int64 A1, A2, B1, B2;
  cin >> A1 >> A2 >> B1 >> B2;
  int64 num = 0;
  for( int64 b = B1 ; b <= B2 ; ++b ) {
    int64 at1 = static_cast<int64>(b * GOLD1);
    int64 at2 = static_cast<int64>(b * GOLD2);
    if( at1 < A1 ) { num += A2 - A1 + 1; }
    else if( at1 < A2 ) { num += A2 - at1; }
    if( A2 <= at2 ) { num += A2 - A1 + 1; }
    else if( A1 <= at2 ) { num += at2 - A1 + 1; }
  }
  return num;
}

int main(void)
{
  int T;
  cin >> T;
  for( int t = 1 ; t <= T ; ++t ) {
    cerr << "Case #" << t << "\n";
    cout << "Case #" << t << ": " << solve() << "\n";
  }
  return 0;
}