이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include <cstdio>
#include <cassert>
#include <algorithm>
#include <vector>
#include <cstring>
#include <iostream>
#include <cmath>
#include <string>
#define FOR(i, a, b) for (int i=(a); i<(b); i++)
#define REP(i, n) FOR(i, 0, n)
#define TRACE(x) cerr << #x << " = " << x << endl
#define _ << " _ " <<
#define X first
#define Y second
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int M = 13, MAX = 13;
int W, H;
int zero_one, one_zero;
void print_mask(int msk) {
  REP(i, W) {
    if (msk >> i & 1) printf("X");
    else printf(".");
  }
}
namespace brute {
  int brute_h;
  bool vis[M+2][MAX+1][1<<(MAX+1)];
  bool has(int msk, int pos) { return (msk >> pos) & 1; }
  void rek(int row, int col, int msk) {
    if (vis[row][col][msk]) return;
    vis[row][col][msk] = true;
    if (row == brute_h) return;
    if (col == W) {
      assert(!has(msk, W));
      rek(row+1, 0, msk);
      return;
    }
    if (msk & 1) rek(row, col+1, msk>>1);
    else {
      //up and up-left
      if (col && !has(msk, W) && !has(msk, W-1)) {
        int nmask = (msk | (1<<W) | (1<<(W-1))) >> 1;
        rek(row, col+1, nmask);
      }
      //up and up-right
      if (col != W-1 && !has(msk, W)) {
        int nmask = ((msk | (1<<W)) | (1<<(W+1))) >> 1;
        rek(row, col+1, nmask);
      }
      //right and up-right
      if (col != W-1 && !has(msk, 1)) {
        int nmask = (msk | (1<<(W+1)) | (1<<1)) >> 1;
        rek(row, col+1, nmask);
      }
      //up and right
      if (col != W-1 && !has(msk, W) && !has(msk, 1)) {
        int nmask = (msk | (1<<W) | (1<<1)) >> 1;
        rek(row, col+1, nmask);
      }
    }
  }
  vector <bool> reaches(const vector <bool> &V, int len) {
    assert(len >= 0 && len <= M);
    if (len == 0) return V;
    brute_h = len;
    memset(vis, 0, sizeof vis);
    REP(i, 1<<W)
      if (V[i])
        rek(0, 0, i);
    vector <bool> R((1<<W), false);
    REP(i, 1<<W)
      R[i] = vis[len][0][i];
    return R;
  }
}
vector <bool> reaches_single(int a, int len) {
  assert(len >= M);
  vector <bool> R(1<<W);
  if (W % 2 && a == zero_one) return R;
  if (W == 3) {
    int pc = __builtin_popcount(a);
    if (pc == 1) {
      R[zero_one] = true;
      if (len % 2) R[5 ^ a] = true;
      else R[a] = true;
    }
    else if (pc == 2) {
      if (a == one_zero) R[3] = R[6] = true;
      else if (len % 2) R[9-a] = true;
      else R[a] = true;
    }
    else {
      if (len % 2) R[7 ^ a] = true;
      else R[a] = true;
    }
    return R;
  }
  int pc = __builtin_popcount(a);
  len %= 3;
  REP(i, 1<<W)
    if (W % 2 == 0 || i != one_zero)
      R[i] = ((pc - len * W - __builtin_popcount(i)) % 3 == 0);
  return R;
}
vector <bool> reaches(const vector <bool> &V, int len) {
  if (len < M)
    return brute::reaches(V, len);
  vector <bool> R(1<<W);
  if (W <= 3) {
    REP(i, 1<<W)  {
      if (V[i]) {
        vector <bool> T = reaches_single(i, len);
        REP(j, 1<<W)
          R[j] = R[j] | T[j];
      }
    }
    return R;
  }
  bool has[3] = {false};
  REP(i, 1<<W) {
    if (V[i]) {
      if (i == zero_one && (W % 2)) continue;
      int pc = __builtin_popcount(i) % 3;
      if (has[pc]) continue;
      has[pc] = true;
      auto T = reaches_single(i, len);
      REP(j, 1<<W)
        R[j] = R[j] | T[j];
    }
  }
  return R;
}
vector <P> Mask_rows;
void load() {
  int k;
  scanf("%d%d%d", &W, &H, &k);
  vector <P> Tiles(k);
  REP(i, k) {
    int a, b;
    scanf("%d%d", &a, &b);
    Tiles[i] = P(b-1, a-1);
  }
  sort(Tiles.begin(), Tiles.end());
  for (int i=0; i<k; ) {
    int msk = 0, j = i;
    for (; j<k && Tiles[i].X == Tiles[j].X; j++)
      msk |= 1<<Tiles[j].Y;
    Mask_rows.push_back(P(Tiles[i].X, msk));
    i=j;
  }
  Mask_rows.push_back(P(H, (1<<W) - 1));
}
int main()
{
  load();
  REP(i, W) {
    if (i & 1) zero_one |= 1<<i;
    else one_zero |= 1<<i;
  }
  vector <bool> Curr_masks(1<<W, false);
  Curr_masks[0] = true;
  int prev=0;
  for (auto msk_row : Mask_rows) {
    int len = msk_row.X - prev;
    vector <bool> T = reaches(Curr_masks, len);
    vector <bool> Nxt(1<<W, false);
    REP(i, 1<<W)
      if (T[i] && !(i & msk_row.Y))
        Nxt[i | msk_row.Y] = true;
    Curr_masks = Nxt;
    prev = msk_row.X;
  }
  if (Curr_masks[(1<<W)-1]) printf("YES\n");
  else printf("NO\n");
  return 0;
}
컴파일 시 표준 에러 (stderr) 메시지
ltrominoes.cpp: In function 'void load()':
ltrominoes.cpp:168:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  168 |   scanf("%d%d%d", &W, &H, &k);
      |   ~~~~~^~~~~~~~~~~~~~~~~~~~~~
ltrominoes.cpp:173:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  173 |     scanf("%d%d", &a, &b);
      |     ~~~~~^~~~~~~~~~~~~~~~| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... |