Problem:
Problem B:
Bubble Puzzle
A browser-based puzzle game called "Bubble Puzzle" is now popular on the Internet.
The puzzle is played on a 4 × 4 grid, and initially there are several bubbles in the grid squares. Each bubble has a state expressed by a positive integer, and the state changes when the bubble gets stimulated. You can stimulate a bubble by clicking on it, and this will increase the bubble's state by 1. You can also click on an empty square. In this case, a bubble with state 1 is newly created in the square.
When the state of a bubble becomes 5 or higher, the bubble blows up and disappears, and small waterdrops start flying in four directions (up, down, left and right). These waterdrops move one square per second. At the moment when a bubble blows up, 4 waterdrops are in the square the bubble was in, and one second later they are in the adjacent squares, and so on.
A waterdrop disappears either when it hits a bubble or goes outside the grid. When a waterdrop hits a bubble, the state of the bubble gets increased by 1. Similarly, if a bubble is hit by more than one water drop at the same time, its state is increased by the number of the hitting waterdrops. Please note that waterdrops do not collide with each other.
As shown in the figure above, waterdrops created by a blow-up may cause other blow-ups. In other words, one blow-up can trigger a chain reaction. You are not allowed to click on any square while waterdrops are flying (i.e., you have to wait until a chain reaction ends). The goal of this puzzle is to blow up all the bubbles and make all the squares empty as quick as possible.
Your mission is to calculate the minimum number of clicks required to solve the puzzle.
Input
The input consists of 4 lines, each contains 4 nonnegative integers smaller than 5. Each integer describes the initial states of bubbles on grid squares. 0 indicates that the corresponding square is empty.
Output
Output the minimum number of clicks to blow up all the bubbles on the grid in a line. If the answer is bigger than 5, output -1 instead. No extra characters should appear in the output.
Sample Input 1
4 4 4 4
4 4 4 4
4 4 4 4
4 4 4 4
Output for the Sample Input 1
1
Sample Input 2
2 4 4 1
2 4 4 1
2 4 4 1
2 4 4 1
Output for the Sample Input 2
5
Sample Input 3
2 4 3 4
2 2 4 4
3 3 2 2
2 3 3 3
Output for the Sample Input 3
3

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
using namespace std;

int ans = 6;

struct drop{
    int y, x, d;

    int id;

    bool operator==(const drop & rhs) const {
        return y == rhs.y && x == rhs.x && d == rhs.d;
    }
};

template<typename T>
bool chmax(T &a, T b){
    if(a < b){
        a = b;
        return true;
    }
    return false;
}

int cnt = 0;

vector< vector<int> > operate(vector< vector<int> > v, int i, int j){
    ++v[i][j];

    if(v[i][j] < 5){
        return v;
    }

    v[i][j] = 0;

    vector<drop> d;
    for(int k = 0 ; k < 4 ; ++k){
        d.push_back({i, j, k, cnt++});
    }

    while(!d.empty()){
        // cout << endl << i << " " << j << " " << d.size() << endl;
        for(int k = 0 ; k < d.size() ; ++k){
            auto &t = d[k];
            // cout << t.y << " " << t.x << " " << t.d << " " << t.id << " -> ";
            if(t.d == 0){
                ++t.y;
            }else if(t.d == 1){
                ++t.x;
            }else if(t.d == 2){
                --t.y;
            }else{
                --t.x;
            }
            // cout << t.y << " " << t.x << " " << t.d << " " << t.id << endl;
            if(t.y < 0 || 4 <= t.y || t.x < 0 || 4 <= t.x){
                d.erase(d.begin() + k);
                --k;
                continue;
            }
            if(v[t.y][t.x] > 0){
                ++v[t.y][t.x];
                d.erase(d.begin() + k);
                --k;
                continue;
            }
        }
        for(int k = 0 ; k < 4 ; ++k){
            for(int l = 0 ; l < 4 ; ++l){
                // cout << v[k][l] << " ";
                if(v[k][l] >= 5){
                    v[k][l] = 0;
                    for(int m = 0 ; m < 4 ; ++m){
                        d.push_back({k, l, m, cnt++});
                    }
                }
            }
            // cout << endl;
        }
    }

    return v;
}

void dfs(int depth, vector< vector<int> > v){
    if(depth >= ans){
        return;
    }

    bool flag = true;
    for(int i = 0 ; i < 4 ; ++i){
        for(int j = 0 ; j < 4 ; ++j){
            flag &= v[i][j] == 0;
        }
    }

    if(flag){
        ans = min(ans, depth);
        return;
    }

    for(int i = 0 ; i < 4 ; ++i){
        for(int j = 0 ; j < 4 ; ++j){
            if(0 < v[i][j]){
                dfs(depth + 1, operate(v, i, j));
            }
        }
    }

    return;
}

int main(){
    vector< vector<int> > v(4, vector<int>(4));
    for(int i = 0 ; i < 4 ; ++i){
        for(int j = 0 ; j < 4 ; ++j){
            cin >> v[i][j];
        }
    }

    dfs(0, v);

    if(ans < 6){
        cout << ans << endl;
    }else{
        cout << -1 << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 1930
memory_kb: 3448
final_rank: 15

code_snippet: #include <iostream>
#include <cstring>

using namespace std;

int  a[6][6];
int  cur[6][6];
int  drops2[6][6][4];
int  drops[6][6][4];
int  dx[4]={1,0,-1,0};
int  dy[4]={0,1,0,-1};

bool ok()
{
          for(int i=1;i<=4;i++)
                    for(int  j=1;j<=4;j++)
                              if(cur[i][j])
                                        return 0;
          return 1;
}

void drop(int p1,int p2)
{
          if(cur[p1][p2]==0) return;
          memset(drops,0,sizeof(drops));
          cur[p1][p2]++;
          if(cur[p1][p2]>=5)
          {
                    cur[p1][p2]=0;
                    for(int  i=1;i<=4;i++)
                              drops[p1+dx[i-1]][p2+dy[i-1]][i-1]++;
                    for(int sec=0;sec<20;sec++)
                    {
                              if(ok())
                                        return;
                              memset(drops2,0,sizeof(drops2));
                              for(int  i=1;i<=4;i++)
                                        for(int  j=1;j<=4;j++)
                                        {
                                                  if(cur[i][j]!=0)
                                                  {
                                                            for(int  k=0;k<4;k++)
                                                            {
                                                                      cur[i][j]+=drops[i][j][k];
                                                                      drops[i][j][k]=0;
                                                            }
                                                            if(cur[i][j]>=5)
                                                            {
                                                                      cur[i][j]=0;
                                                                      for(int  k=0;k<4;k++)
                                                                      {
                                                                                if(i+dx[k]>=1 && i+dx[k]<=4 && j+dy[k]>=1 && j+dy[k]<=4)
                                                                                          drops2[i+dx[k]][j+dy[k]][k]++;
                                                                      }
                                                            }
                                                  }
                                                  else
                                                  {
                                                            for(int  k=0;k<4;k++)
                                                                      if(i+dx[k]>=1 && i+dx[k]<=4 && j+dy[k]>=1 && j+dy[k]<=4)
                                                                                drops2[i+dx[k]][j+dy[k]][k]+=drops[i][j][k];
                                                  }
                                        }
                    for(int pp1=0;pp1<=5;pp1++)
                              for(int pp2=0;pp2<=5;pp2++)
                                        for(int pp3=0;pp3<4;pp3++)
                                                  drops[pp1][pp2][pp3]=drops2[pp1][pp2][pp3];
                    }
          }
}

int main()
{
          //freopen("INPUT.txt","r",stdin);
          int okk=1;
          for(int  i=1;i<=4;i++)
                    for(int  j=1;j<=4;j++)
                    {
                              cin>>a[i][j];
                              if(a[i][j])
                                        okk=0;
                    }
                    if(okk)
                    {
                              cout<<0<<endl;
                              return 0;
                    }


          int  ans=6;
          for(int  i1=1;i1<=4;i1++)
                    for(int  j1=1;j1<=4;j1++)
                              for(int  i2=1;i2<=4;i2++)
                                        for(int  j2=1;j2<=4;j2++)
                                                  for(int  i3=1;i3<=4;i3++)
                                                            for(int  j3=1;j3<=4;j3++)
                                                                      for(int  i4=1;i4<=4;i4++)
                                                                                for(int  j4=1;j4<=4;j4++)
                                                                                          for(int  i5=1;i5<=4;i5++)
                                                                                                    for(int  j5=1;j5<=4;j5++)
                                                                                                    {
                                                                                                              for(int pp1=1;pp1<=4;pp1++)
                                                                                                              for(int pp2=1;pp2<=4;pp2++)
                                                                                                                        cur[pp1][pp2]=a[pp1][pp2];
                                                                                                              drop(i1,j1);
                                                                                                              if(ok())
                                                                                                                        ans=min(ans,1 );
                                                                                                              if(ans==1) {cout<<1<<endl; return 0;}
                                                                                                              drop(i2,j2);
                                                                                                              if(ok())
                                                                                                                        ans=min(ans,2 );
                                                                                                              if(ans==2) continue;
                                                                                                              drop(i3,j3);
                                                                                                              if(ok())
                                                                                                                        ans=min(ans,3);
                                                                                                              if(ans==3) continue;
                                                                                                              drop(i4,j4);
                                                                                                              if(ok())
                                                                                                                        ans=min(ans,4 );
                                                                                                              if(ans==4) continue;
                                                                                                              drop(i5,j5);
                                                                                                              if(ok())
                                                                                                                        ans=min(ans,5 );
                                                                                                    }
          if(ans==6)
                    cout<<-1<<endl;
          else
                    cout<<ans<<endl;

}
accuracy: 1
time_ms: 2900
memory_kb: 3444
final_rank: 17

code_snippet: // AOJ #2380 Bubble Puzzle
// 2025.2.23

#include <bits/stdc++.h>
using namespace std;

const int N = 4;

string encode(const array<array<int, N>, N>& board) {
    string s;
    for (int i = 0; i < N; i++){
        for (int j = 0; j < N; j++) s.push_back('0' + board[i][j]);
    }
    return s;
}

bool check(const array<array<int, N>, N>& board) {
    for (int i = 0; i < N; i++){
        for (int j = 0; j < N; j++) if(board[i][j] != 0) return false;
    }
    return true;
}

struct Drop { int r, c, dr, dc; };

array<array<int, N>, N> simulate(array<array<int, N>, N> board) {
    vector<Drop> drops;
    while (true) {
        bool exploded = false;
        for (int i = 0; i < N; i++){
            for (int j = 0; j < N; j++){
                if(board[i][j] >= 5){
                    exploded = true;
                    board[i][j] = 0;
                    drops.push_back({i, j, -1, 0});
                    drops.push_back({i, j, 1, 0});
                    drops.push_back({i, j, 0, -1});
                    drops.push_back({i, j, 0, 1});
                }
            }
        }

        if(drops.empty() && !exploded) break;

        vector<Drop> newDrops;
        array<array<int, N>, N> add = {0};
        for(auto &d : drops) {
            int nr = d.r + d.dr;
            int nc = d.c + d.dc;
            if(nr < 0 || nr >= N || nc < 0 || nc >= N) continue;
            if(board[nr][nc] > 0) add[nr][nc]++;
            else newDrops.push_back({nr, nc, d.dr, d.dc});
        }
        for (int i = 0; i < N; i++){
            for (int j = 0; j < N; j++){
                if(add[i][j] > 0) board[i][j] += add[i][j];
            }
        }
        drops = move(newDrops);
    }
    return board;
}

int bfs(array<array<int, N>, N> start) {
    if(check(start)) return 0;
    set<string> seen;
    queue<pair<array<array<int, N>, N>, int>> q;
    q.push({start, 0});
    seen.insert(encode(start));

    while(!q.empty()){
        auto cur = q.front();
        q.pop();
        auto board = cur.first;
        int clicks = cur.second;
        if(clicks >= 5) continue;

        for (int i = 0; i < N; i++){
            for (int j = 0; j < N; j++){
                auto nextBoard = board;
                nextBoard[i][j] = (nextBoard[i][j] == 0) ? 1 : nextBoard[i][j] + 1;

                nextBoard = simulate(nextBoard);

                if(check(nextBoard)) return clicks + 1;

                string code = encode(nextBoard);
                if(seen.count(code) == 0){
                    seen.insert(code);
                    q.push({nextBoard, clicks+1});
                }
            }
        }
    }
    return -1;
}

int main() {
    array<array<int, N>, N> board;
    for (int i = 0; i < N; i++){
        for (int j = 0; j < N; j++) cin >> board[i][j];
    }
    cout << bfs(board) << endl;
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 11196
final_rank: 13

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

int dx[4] = {1,0,-1,0}, dy[4] = {0,1,0,-1};

vector<vector<int>> Simulation(vector<vector<int>> A, int X, int Y) {
    A[X][Y]++;
    if (A[X][Y] < 5) return A;
    bool B[4][4][4] = {};
while(1) {
    bool ischange = false;
    rep(i,0,4) {
        rep(j,0,4) {
            if (A[i][j] >= 5) {
                A[i][j] = 0;
                ischange = true;
                rep(k,0,4) {
                    B[i][j][k] = true;
                }
            }
        }
    }
    bool NB[4][4][4] = {};
    rep(i,0,4) {
        rep(j,0,4) {
            rep(k,0,4) {
                NB[i][j][k] = false;
            }
        }
    }
    rep(i,0,4) {
        rep(j,0,4) {
            rep(k,0,4) {
                if (B[i][j][k]) {
                    ischange = true;
                    int ni = i+dx[k], nj = j+dy[k];
                    if (0 <= ni && ni < 4 && 0 <= nj && nj < 4) {
                        if (A[ni][nj] == 0) {
                            NB[ni][nj][k] = true;
                        }
                        else {
                            A[ni][nj]++;
                        }
                    }
                }
            }
        }
    }
    rep(i,0,4) {
        rep(j,0,4) {
            rep(k,0,4) {
                B[i][j][k] = NB[i][j][k];
            }
        }
    }
    if (!ischange) break;
}
    return A;
}

int ANS = 6;
void DFS(vector<vector<int>> A, int Dep) {
    if (Dep >= ANS) return;
    bool check = true;
    rep(i,0,4) rep(j,0,4) if (A[i][j] != 0) check = false;
    if (check) {
        chmin(ANS,Dep);
        return;
    }
    rep(i,0,4) {
        rep(j,0,4) {
            if (A[i][j] == 0) continue;
            DFS(Simulation(A,i,j),Dep+1);
        }
    }
}

int main() {
    vector A(4,vector<int>(4));
    rep(i,0,4) rep(j,0,4) cin >> A[i][j];
    DFS(A,0);
    cout << (ANS == 6 ? -1 : ANS) << endl;
}
accuracy: 1
time_ms: 3390
memory_kb: 3440
final_rank: 18

code_snippet: #include <bits/stdc++.h>

constexpr int n{4};
constexpr int m{5};
std::array<std::array<int, 4>, 4> a;
std::vector<std::pair<int, int>> op;

constexpr int dx[4]{1, 0, -1, 0};
constexpr int dy[4]{0, 1, 0, -1};

auto in(int x, int y) {
    return 0 <= x and x < n and 0 <= y and y < n;
}

int calc() {
    // std::cout << "calc called" << std::endl;
    decltype(a) b = a;

    auto empty{[&](int x, int y) -> bool {
        return b[x][y] == 0;
    }};
    auto check{[&]() -> bool {
        bool res{true};
        for (int i{} ; i < n ; i++) for (int j{} ; j < n ; j++) {
            res &= empty(i, j);
        }
        return res;
    }};

    auto explo{[&](int x, int y) -> bool {
        return b[x][y] >= m;
    }};

    auto click{[&](int x, int y) -> void {
        // std::cout << "click " << x << ' ' << y << std::endl;
        b[x][y]++; 
        using tuple = std::tuple<int, int, int, int>;
        std::vector<tuple> water;
        if (explo(x, y)) {
            b[x][y] = 0;
            for (int i{} ; i < 4 ; i++) water.emplace_back(x, y, dx[i], dy[i]);
        }
        int debug{};
        while (water.size()) {
            std::vector<tuple> nextWater;
            for (auto [px, py, vx, vy] : water) {
                if (empty(px, py)) {
                    px += vx;
                    py += vy;
                    if (in(px, py)) {
                        nextWater.emplace_back(px, py, vx, vy);
                    }
                }
                else {
                    b[px][py]++;
                }
            }
            for (int i{} ; i < n ; i++) for (int j{} ; j < n ; j++) {
                if (explo(i, j)) {
                    b[i][j] = 0;
                    for (int k{} ; k < 4 ; k++) {
                        nextWater.emplace_back(i, j, dx[k], dy[k]);
                    }
                }
            }
            //for (int i{} ; i < n ; i++) {
            //    for (int j{} ; j < n ; j++) {
            //        std::cout << b[i][j] << ' ';
            //    }
            //    std::cout << std::endl;
            //}
            water = std::move(nextWater);
            // if (++debug == 2) exit(0);
        }
    }};

    for (int i{} ; i <= m ; i++) {
        if (check()) return i;
        // std::cout << "operation " << i << std::endl;
        if (i < m) click(op[i].first, op[i].second);
    }
    return m + 1;
}

int dfs(int v) {
    if (v == m) {
        return calc();
    }
    int res{m + 1};
    for (int i{} ; i < n ; i++) for (int j{} ; j < n ; j++) {
        op.emplace_back(i, j);
        res = std::min(res, dfs(v + 1));
        op.pop_back();
    }
    return res;
}

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);

    for (auto& x : a) for (auto& v : x) std::cin >> v;

    int ans{dfs(0)};
    if (ans <= m) {
        std::cout << ans << '\n';
    }
    else {
        std::cout << -1 << '\n';
    }
}
accuracy: 1
time_ms: 1890
memory_kb: 3456
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;

const vector<int> dx = { 1, 0, -1, 0 };
const vector<int> dy = { 0, 1, 0, -1 };

struct water {
	int x, y, d;
};

bool inside(const water& w) {
	return 0 <= w.x && w.x <= 3 && 0 <= w.y && w.y <= 3;
}

vector<int> process(vector<int> s) {
	vector<water> drops;
	while (true) {
		for (int i = 0; i < 16; i++) {
			if (s[i] >= 5) {
				s[i] = 0;
				for (int j = 0; j < 4; j++) {
					drops.push_back(water{i / 4, i % 4, j});
				}
			}
		}
		if (drops.empty()) {
			break;
		}
		for (water& w : drops) {
			w.x += dx[w.d];
			w.y += dy[w.d];
		}
		vector<water> ndrops;
		for (water w : drops) {
			if (inside(w)) {
				if (s[w.x * 4 + w.y] >= 1) {
					s[w.x * 4 + w.y] += 1;
				}
				else {
					ndrops.push_back(w);
				}
			}
		}
		drops = ndrops;
	}
	return s;
}

int main() {
	vector<int> a(16);
	for (int i = 0; i < 16; i++) {
		cin >> a[i];
	}
	bool found = false;
	int depth = 0;
	while (depth <= 5) {
		for (int i = 0; i < (1 << (4 * depth)); i++) {
			vector<int> s = a;
			for (int j = 0; j < depth; j++) {
				int pos = (i >> (4 * j)) & 15;
				s[pos] += 1;
				s = process(s);
			}
			if (s == vector<int>(16, 0)) {
				found = true;
				break;
			}
		}
		if (found) {
			break;
		}
		depth += 1;
	}
	cout << (depth != 6 ? depth : -1) << endl;
	return 0;
}
accuracy: 1
time_ms: 590
memory_kb: 3428
final_rank: 8

code_snippet: #include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
struct data {
  int x, y, dir, t;
  data() {}
  data(int xx, int yy, int dd, int tt) {
    x = xx;
    y = yy;
    dir = dd;
    t = tt;
  }
};
int res = 6;
int fie[6][4][4];
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
void bubble(int c) {
  queue<data> que;
  for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 4; j++) {
      if (fie[c][i][j] >= 5) {
        fie[c][i][j] = 0;
        for (int k = 0; k < 4; k++) {
          que.push(data(j, i, k, 0));
        }
      }
    }
  }
  int prev = 0;
  while (que.size()) {
    data q = que.front();
    if (prev != q.t) {
      for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
          if (fie[c][i][j] >= 5) {
            fie[c][i][j] = 0;
            for (int k = 0; k < 4; k++) {
              que.push(data(j, i, k, q.t + 1));
            }
          }
        }
      }
    }
    prev = q.t;
    que.pop();
    int nx = q.x + dx[q.dir], ny = q.y + dy[q.dir];
    if (nx < 0 || nx >= 4 || ny < 0 || ny >= 4)
      continue;
    if (fie[c][ny][nx] > 0) {
      fie[c][ny][nx]++;
      if (fie[c][ny][nx] >= 5)
        que.push(data(-5, -5, 0, q.t + 1));
    } else
      que.push(data(nx, ny, q.dir, q.t + 1));
  }
}
void dfs(int cnt) {
  if (res <= cnt)
    return;
  bool flag = true;
  for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 4; j++) {
      if (fie[cnt][i][j] > 0)
        flag = false;
    }
  }
  if (flag) {
    res = cnt;
    return;
  }
  for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 4; j++) {
      fie[cnt][i][j]++;
      for (int k = 0; k < 4; k++) {
        for (int l = 0; l < 4; l++) {
          fie[cnt + 1][k][l] = fie[cnt][k][l];
        }
      }
      bubble(cnt + 1);
      dfs(cnt + 1);
      fie[cnt][i][j]--;
    }
  }
}
int main(void) {
  for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 4; j++) {
      scanf("%d", &fie[0][i][j]);
    }
  }
  dfs(0);
  printf("%d\n", res == 6 ? -1 : res);
  return 0;
}
accuracy: 1
time_ms: 4860
memory_kb: 2768
final_rank: 19

code_snippet: #include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
struct data {
  int x, y, dir, t;
  data() {}
  data(int xx, int yy, int dd, int tt) {
    x = xx;
    y = yy;
    dir = dd;
    t = tt;
  }
};
int res = 6;
int fie[6][4][4];
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
void bubble(int c) {
  queue<data> que;
  for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 4; j++) {
      if (fie[c][i][j] >= 5) {
        fie[c][i][j] = 0;
        for (int k = 0; k < 4; k++) {
          que.push(data(j, i, k, 0));
        }
      }
    }
  }
  int prev = 0;
  while (que.size()) {
    data q = que.front();
    if (prev != q.t) {
      for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
          if (fie[c][i][j] >= 5) {
            fie[c][i][j] = 0;
            for (int k = 0; k < 4; k++) {
              que.push(data(j, i, k, q.t + 1));
            }
          }
        }
      }
    }
    prev = q.t;
    que.pop();
    int nx = q.x + dx[q.dir], ny = q.y + dy[q.dir];
    if (nx < 0 || nx >= 4 || ny < 0 || ny >= 4)
      continue;
    if (fie[c][ny][nx] > 0) {
      fie[c][ny][nx]++;
      if (fie[c][ny][nx] >= 5)
        que.push(data(-5, -5, 0, q.t + 1));
    } else
      que.push(data(nx, ny, q.dir, q.t + 1));
  }
}
void dfs(int cnt) {
  if (res <= cnt)
    return;
  bool flag = true;
  for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 4; j++) {
      if (fie[cnt][i][j] > 0)
        flag = false;
    }
  }
  if (flag) {
    res = cnt;
    return;
  }
  if (cnt == 5)
    return;
  for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 4; j++) {
      fie[cnt][i][j]++;
      for (int k = 0; k < 4; k++) {
        for (int l = 0; l < 4; l++) {
          fie[cnt + 1][k][l] = fie[cnt][k][l];
        }
      }
      bubble(cnt + 1);
      dfs(cnt + 1);
      fie[cnt][i][j]--;
    }
  }
}
int main(void) {
  for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 4; j++) {
      scanf("%d", &fie[0][i][j]);
    }
  }
  dfs(0);
  printf("%d\n", res == 6 ? -1 : res);
  return 0;
}
accuracy: 1
time_ms: 310
memory_kb: 2768
final_rank: 1

code_snippet: #include <algorithm>
#include <assert.h>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);
#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c)                                                           \
  for (__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))
typedef vector<char> Array;
typedef vector<Array> Matrix;
struct Water {
  char x;
  char y;
  char dir;
  Water() { ; }
  Water(int x, int y, int dir) : x(x), y(y), dir(dir) { ; }
};
const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};
int maxDepth;
int calc(int depth, const Matrix &field);
int NextState(int depth, Matrix field, int sx, int sy) {
  if (field[sy][sx] != 4) {
    field[sy][sx]++;
  } else {
    field[sy][sx] = 0;
    vector<Water> waters;
    REP(dir, 4) { waters.push_back(Water(sx, sy, dir)); }
    while (!waters.empty()) {
      vector<Water> nwaters;
      vector<char> end;
      FORIT(it, waters) {
        int nx = it->x + dx[(int)it->dir];
        int ny = it->y + dy[(int)it->dir];
        if (nx < 0 || nx >= 4 || ny < 0 || ny >= 4) {
          continue;
        }
        if (field[ny][nx] != 0) {
          field[ny][nx]++;
          if (field[ny][nx] == 5) {
            end.push_back((ny << 4) + nx);
          }
        } else {
          nwaters.push_back(Water(nx, ny, it->dir));
        }
      }
      FORIT(it, end) {
        int x = *it & 3;
        int y = *it >> 4;
        field[y][x] = 0;
        REP(dir, 4) { nwaters.push_back(Water(x, y, dir)); }
      }
      waters = nwaters;
    }
  }
  return calc(depth + 1, field);
}
int calc(int depth, const Matrix &field) {
  {
    int sum = 0;
    REP(y, 4) REP(x, 4) { sum += field[y][x]; }
    if (sum == 0) {
      return depth;
    }
  }
  if (depth == maxDepth) {
    return 1 << 30;
  }
  int ret = 1 << 30;
  REP(y, 4) {
    REP(x, 4) {
      if (field[y][x] != 0) {
        ret = min(ret, NextState(depth, field, x, y));
        if (ret == maxDepth) {
          return ret;
        }
      }
    }
  }
  return ret;
}
int main() {
  while (true) {
    Matrix field(4, Array(4, 0));
    REP(y, 4) {
      REP(x, 4) {
        int v;
        if (scanf("%d", &v) <= 0) {
          return 0;
        }
        field[y][x] = v;
      }
    }
    int ans = -1;
    REP(iter, 6) {
      maxDepth = iter;
      if (calc(0, field) == maxDepth) {
        ans = maxDepth;
        break;
      }
    }
    printf("%d\n", ans);
  }
}
accuracy: 1
time_ms: 290
memory_kb: 3284
final_rank: 2

code_snippet: #include <algorithm>
#include <assert.h>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);
#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c)                                                           \
  for (__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))
typedef vector<char> Array;
typedef vector<Array> Matrix;
struct Water {
  char x;
  char y;
  char dir;
  Water() { ; }
  Water(int x, int y, int dir) : x(x), y(y), dir(dir) { ; }
};
const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};
Matrix NextState(Matrix field, int sx, int sy) {
  if (field[sy][sx] != 4) {
    field[sy][sx]++;
  } else {
    field[sy][sx] = 0;
    vector<Water> waters;
    REP(dir, 4) { waters.push_back(Water(sx, sy, dir)); }
    while (!waters.empty()) {
      vector<Water> nwaters;
      vector<char> end;
      FORIT(it, waters) {
        int nx = it->x + dx[(int)it->dir];
        int ny = it->y + dy[(int)it->dir];
        if (nx < 0 || nx >= 4 || ny < 0 || ny >= 4) {
          continue;
        }
        if (field[ny][nx] != 0) {
          field[ny][nx]++;
          if (field[ny][nx] == 5) {
            end.push_back((ny << 4) + nx);
          }
        } else {
          nwaters.push_back(Water(nx, ny, it->dir));
        }
      }
      FORIT(it, end) {
        int x = *it & 3;
        int y = *it >> 4;
        field[y][x] = 0;
        REP(dir, 4) { nwaters.push_back(Water(x, y, dir)); }
      }
      waters = nwaters;
    }
  }
  return field;
}
bool OK(const Matrix &field) {
  int sum = 0;
  REP(y, 4) REP(x, 4) { sum += field[y][x]; }
  return sum == 0;
}
int main() {
  while (true) {
    Matrix field(4, Array(4, 0));
    REP(y, 4) {
      REP(x, 4) {
        int v;
        if (scanf("%d", &v) <= 0) {
          return 0;
        }
        field[y][x] = v;
      }
    }
    int ans = -1;
    set<Matrix> visit;
    queue<Matrix> que[2];
    que[0].push(field);
    REP(iter, 5) {
      if (OK(field)) {
        ans = 0;
        break;
      }
      int prev = iter & 1;
      int next = prev ^ 1;
      while (!que[prev].empty()) {
        Matrix matrix = que[prev].front();
        que[prev].pop();
        REP(y, 4) {
          REP(x, 4) {
            if (field[y][x] != 0) {
              Matrix nmatrix = NextState(matrix, x, y);
              if (visit.count(nmatrix)) {
                continue;
              }
              visit.insert(nmatrix);
              if (OK(nmatrix)) {
                ans = iter + 1;
                goto end;
              } else {
                que[next].push(nmatrix);
              }
            }
          }
        }
      }
    }
  end:;
    printf("%d\n", ans);
  }
}
accuracy: 1
time_ms: 70
memory_kb: 14984
final_rank: 16

code_snippet: #include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;
#define FOR(i, k, n) for (int i = (k); i < (int)(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORIT(i, c)                                                            \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
template <class T> void debug(T begin, T end) {
  for (T i = begin; i != end; ++i)
    cerr << *i << " ";
  cerr << endl;
}
inline bool valid(int x, int y, int W, int H) {
  return (x >= 0 && y >= 0 && x < W && y < H);
}
typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
int min_ans = 6;
const int N = 4;
int a[4][4];
struct Bubble {
  int x, y, r;
  Bubble() {}
  Bubble(int x, int y, int r) : x(x), y(y), r(r) {}
};
int dfs(int K) {
  if (K >= min_ans)
    return INF;
  stack<Bubble> stk;
  do {
    stack<Bubble> nstk;
    while (!stk.empty()) {
      Bubble b = stk.top();
      stk.pop();
      int nx = b.x + dx[b.r];
      int ny = b.y + dy[b.r];
      if (!valid(nx, ny, N, N))
        continue;
      if (a[ny][nx] > 0) {
        a[ny][nx]++;
      } else {
        nstk.push(Bubble(nx, ny, b.r));
      }
    }
    stk = nstk;
    REP(y, N) REP(x, N) if (a[y][x] >= 5) {
      a[y][x] = 0;
      REP(r, 4) stk.push(Bubble(x, y, r));
    }
  } while (!stk.empty());
  bool end = true;
  REP(i, N) REP(j, N) if (a[i][j] != 0) end = false;
  if (end)
    return min_ans = K;
  int tmp[4][4];
  memcpy(tmp, a, sizeof(a));
  int res = INF;
  REP(i, N) REP(j, N) {
    a[i][j]++;
    res = min(res, dfs(K + 1));
    memcpy(a, tmp, sizeof(a));
  }
  return res;
}
int main() {
  while (true) {
    min_ans = 6;
    REP(i, N) REP(j, N) cin >> a[i][j];
    if (cin.eof())
      break;
    int ans = dfs(0);
    if (ans == INF)
      cout << -1 << endl;
    else
      cout << ans << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 750
memory_kb: 3140
final_rank: 11

code_snippet: #include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;
#define FOR(i, k, n) for (int i = (k); i < (int)(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORIT(i, c)                                                            \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
template <class T> void debug(T begin, T end) {
  for (T i = begin; i != end; ++i)
    cerr << *i << " ";
  cerr << endl;
}
inline bool valid(int x, int y, int W, int H) {
  return (x >= 0 && y >= 0 && x < W && y < H);
}
typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
int min_ans = 6;
const int N = 4;
int a[4][4];
struct Bubble {
  int x, y, r;
  Bubble() {}
  Bubble(int x, int y, int r) : x(x), y(y), r(r) {}
};
int dfs(int K) {
  if (K >= min_ans)
    return INF;
  stack<Bubble> stk;
  do {
    stack<Bubble> nstk;
    while (!stk.empty()) {
      Bubble b = stk.top();
      stk.pop();
      int nx = b.x + dx[b.r];
      int ny = b.y + dy[b.r];
      if (!valid(nx, ny, N, N))
        continue;
      if (a[ny][nx] > 0) {
        a[ny][nx]++;
      } else {
        nstk.push(Bubble(nx, ny, b.r));
      }
    }
    stk = nstk;
    REP(y, N) REP(x, N) if (a[y][x] >= 5) {
      a[y][x] = 0;
      REP(r, 4) stk.push(Bubble(x, y, r));
    }
  } while (!stk.empty());
  bool end = true;
  REP(i, N) REP(j, N) if (a[i][j] != 0) end = false;
  if (end)
    return min_ans = K;
  int tmp[4][4];
  memcpy(tmp, a, sizeof(a));
  int res = INF;
  REP(i, N) REP(j, N) if (a[i][j] > 0) {
    a[i][j]++;
    res = min(res, dfs(K + 1));
    memcpy(a, tmp, sizeof(a));
  }
  return res;
}
int main() {
  while (true) {
    min_ans = 6;
    REP(i, N) REP(j, N) cin >> a[i][j];
    if (cin.eof())
      break;
    int ans = dfs(0);
    if (ans == INF)
      cout << -1 << endl;
    else
      cout << ans << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 640
memory_kb: 3140
final_rank: 7

code_snippet: #include "bits/stdc++.h"
using namespace std;

typedef string::const_iterator State;
#define eps 1e-8L
#define MAX_MOD 1000000007LL
#define GYAKU 500000004LL
#define MOD 998244353LL
#define pb push_back
#define mp make_pair
typedef long long ll;
typedef long double ld;
#define REP(a, b) for (long long(a) = 0; (a) < (b); ++(a))
#define ALL(x) (x).begin(), (x).end()

#define int long long
int cur_ans = 6;
vector<int> bonks(vector<int> grid)
{
  queue<pair<int, int>> nexts;
  do
  {
    const int dx[4] = {1, -1, 0, 0};
    queue<pair<int, int>> go;
    while (!nexts.empty())
    {
      pair<int, int> now = nexts.front();
      nexts.pop();
      if (grid[now.first] != 0)
      {
        grid[now.first]++;
        continue;
      }
      go.push(now);
    }
    REP(i, 16)
    {
      if (grid[i] >= 5)
      {
        grid[i] = 0;
        REP(q, 4)
        {
          go.push({i, q});
        }
      }
    }

    while (!go.empty())
    {
      pair<int, int> now = go.front();
      go.pop();
      pair<int, int> tmp = {now.first / 4, now.first % 4};
      tmp.first += dx[now.second];
      tmp.second += dx[3 - now.second];
      if (tmp.first >= 0 and tmp.first < 4 and tmp.second >= 0 and tmp.second < 4)
      {
        nexts.push({tmp.first * 4 + tmp.second, now.second});
      }
    }

  } while (!nexts.empty());
  return grid;
}

void steps(vector<int> grid, int step)
{
  int ok = 1;
  REP(i, 16)
  {
    if (grid[i])
      ok = 0;
  }
  if (ok)
  {
    cur_ans = min(cur_ans, step);
    return;
  }
  if (step >= 5)
  {
    return;
  }

  REP(i, 16)
  {
    if (grid[i] == 0)
      continue;
    grid[i]++;
    steps(bonks(grid), step + 1);
    grid[i]--;
  }
  return;
}
void solve()
{
  vector<int> go;
  REP(i, 16)
  {
    int a;
    cin >> a;
    go.push_back(a);
  }
  steps(go, 0);
  if (cur_ans == 6)
    cur_ans = -1;
  cout << cur_ans << endl;
}

#undef int

// generated by oj-template v4.7.2
// (https://github.com/online-judge-tools/template-generator)
int main()
{
  // Fasterize input/output script
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(100);
  // scanf/printf user should delete this fasterize input/output script

  int t = 1;
  // cin >> t; // comment out if solving multi testcase
  for (int testCase = 1; testCase <= t; ++testCase)
  {
    solve();
  }
  return 0;
}
accuracy: 1
time_ms: 300
memory_kb: 3460
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    vector<vector<int>> a(4, vector<int>(4));
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            cin >> a[i][j];
        }
    }

    vector<vector<vector<int>>> drop(4, vector<vector<int>>(4)), ndrop(4, vector<vector<int>>(4));
    auto click = [&](vector<vector<int>> v, int x, int y) {
        v[x][y]++;
        if (v[x][y] < 5) return v;
        v[x][y] = 0;
        for (int i = 0; i < 4; i++) drop[x][y].emplace_back(i);
        while (true) {
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 4; j++) {
                    while (!drop[i][j].empty()) {
                        int d = drop[i][j].back();
                        drop[i][j].pop_back();
                        int ni = i + dx[d], nj = j + dy[d];
                        if (ni < 0 or 4 <= ni or nj < 0 or 4 <= nj) continue;
                        ndrop[ni][nj].emplace_back(d);
                    }
                }
            }
            swap(drop, ndrop);
            int cnt = 0;
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 4; j++) {
                    if (!v[i][j]) {
                        cnt += drop[i][j].size();
                        continue;
                    }
                    v[i][j] += drop[i][j].size();
                    while (!drop[i][j].empty()) drop[i][j].pop_back();
                    if (v[i][j] >= 5) {
                        v[i][j] = 0;
                        for (int k = 0; k < 4; k++) drop[i][j].emplace_back(k);
                    }
                    cnt += drop[i][j].size();
                }
            }
            if (!cnt) break;
        }
        return v;
    };
    int ans = 6;
    auto dfs = [&](auto self, int dep, vector<vector<int>> v) -> void {
        bool ok = true;
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                if (v[i][j] > 0) {
                    ok = false;
                }
            }
        }
        if (ok) {
            ans = min(ans, dep);
            return;
        }
        if (dep == 5) return;
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                auto u = click(v, i, j);
                self(self, dep + 1, u);
            }
        }
    };

    dfs(dfs, 0, a);
    cout << (ans == 6 ? -1 : ans) << '\n';
    return 0;
}
accuracy: 1
time_ms: 430
memory_kb: 3452
final_rank: 5

code_snippet: #define LOCAL
#include <bits/stdc++.h>
using namespace std;
#pragma region Macros
typedef long long ll;
typedef __int128_t i128;
typedef unsigned int uint;
typedef unsigned long long ull;
#define ALL(x) (x).begin(), (x).end()

template <typename T> istream& operator>>(istream& is, vector<T>& v) {
    for (T& x : v) is >> x;
    return is;
}
template <typename T> ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const pair<T, U>& p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const unordered_map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const multiset<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const unordered_set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const deque<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}

template <int i, typename T> void print_tuple(ostream&, const T&) {}
template <int i, typename T, typename H, class... Args> void print_tuple(ostream& os, const T& t) {
    if (i) os << ',';
    os << get<i>(t);
    print_tuple<i + 1, T, Args...>(os, t);
}
template <typename... Args> ostream& operator<<(ostream& os, const tuple<Args...>& t) {
    os << '{';
    print_tuple<0, tuple<Args...>, Args...>(os, t);
    return os << '}';
}

void debug_out() { cerr << '\n'; }
template <class Head, class... Tail> void debug_out(Head&& head, Tail&&... tail) {
    cerr << head;
    if (sizeof...(Tail) > 0) cerr << ", ";
    debug_out(move(tail)...);
}
#ifdef LOCAL
#define debug(...)                                                                   \
    cerr << " ";                                                                     \
    cerr << #__VA_ARGS__ << " :[" << __LINE__ << ":" << __FUNCTION__ << "]" << '\n'; \
    cerr << " ";                                                                     \
    debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

template <typename T> T gcd(T x, T y) { return y != 0 ? gcd(y, x % y) : x; }
template <typename T> T lcm(T x, T y) { return x / gcd(x, y) * y; }

int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(long long t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int botbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int botbit(long long a) { return a == 0 ? 64 : __builtin_ctzll(a); }
int popcount(signed t) { return __builtin_popcount(t); }
int popcount(long long t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x - y + 1) / y);
}

template <class T1, class T2> inline bool chmin(T1& a, T2 b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T1, class T2> inline bool chmax(T1& a, T2 b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
#pragma endregion

const int INF = 1e9;
const long long IINF = 1e18;
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
const char dir[4] = {'D', 'R', 'U', 'L'};
const long long MOD = 1000000007;
// const long long MOD = 998244353;

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    vector<vector<int>> a(4, vector<int>(4));
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            cin >> a[i][j];
        }
    }

    vector<vector<vector<int>>> drop(4, vector<vector<int>>(4)), ndrop(4, vector<vector<int>>(4));
    auto click = [&](vector<vector<int>> v, int x, int y) {
        v[x][y]++;
        if (v[x][y] < 5) return v;
        v[x][y] = 0;
        for (int i = 0; i < 4; i++) drop[x][y].emplace_back(i);
        while (true) {
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 4; j++) {
                    while (!drop[i][j].empty()) {
                        int d = drop[i][j].back();
                        drop[i][j].pop_back();
                        int ni = i + dx[d], nj = j + dy[d];
                        if (ni < 0 or 4 <= ni or nj < 0 or 4 <= nj) continue;
                        ndrop[ni][nj].emplace_back(d);
                    }
                }
            }
            swap(drop, ndrop);
            int cnt = 0;
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 4; j++) {
                    if (!v[i][j]) {
                        cnt += drop[i][j].size();
                        continue;
                    }
                    v[i][j] += drop[i][j].size();
                    while (!drop[i][j].empty()) drop[i][j].pop_back();
                    if (v[i][j] >= 5) {
                        v[i][j] = 0;
                        for (int k = 0; k < 4; k++) drop[i][j].emplace_back(k);
                    }
                    cnt += drop[i][j].size();
                }
            }
            if (!cnt) break;
        }
        return v;
    };
    int ans = 6;
    auto dfs = [&](auto self, int dep, vector<vector<int>> v) -> void {
        bool ok = true;
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                if (v[i][j] > 0) {
                    ok = false;
                }
            }
        }
        if (ok) {
            ans = min(ans, dep);
            return;
        }
        if (dep == 5) return;
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                auto u = click(v, i, j);
                self(self, dep + 1, u);
            }
        }
    };

    dfs(dfs, 0, a);
    cout << (ans == 6 ? -1 : ans) << '\n';
    return 0;
}
accuracy: 1
time_ms: 450
memory_kb: 3452
final_rank: 6

code_snippet: #pragma GCC ta g("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-7;
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//#include <atcoder/maxflow>
//using namespace atcoder;
//const int mod = 1e9 + 7;
const int mod = 998244353;

bool in(ll y, ll x, ll h, ll w){
    return 0 <= y && y < h && 0 <= x && x < w;
}

void process(vector<vector<int>> &b, int sy, int sx){
    queue<tapu> q;
    b[sy][sx] = 0;
    rep(i,4) q.emplace(sy,sx,i);
    while(!q.empty()){
        queue<tapu> nq;
        vpl v;
        while(!q.empty()){
            int y,x,dir;
            tie(y,x,dir) = q.front(); q.pop();
            y += dy[dir];
            x += dx[dir];
            if(in(y,x,4,4)){
                if(b[y][x] == 0) nq.emplace(y,x,dir);
                else{
                    b[y][x]++;
                    if(b[y][x] == 5) v.emplace_back(y,x);
                }
            }
        }
        for(auto t : v){
            rep(i,4) nq.emplace(t.first,t.second,i);
            b[t.first][t.second] = 0;
        }
        q = nq;
    }
}

using pv = pair<int,vector<vector<int>>>;

int main(){
    vector<vector<int>> a(4,vector<int>(4));
    rep(i,4) rep(j,4) cin >> a[i][j];
    map<vector<vector<int>>,int> dp;
    dp[a] = 0;
    queue<vector<vector<int>>> q;
    q.emplace(a);
    while(!q.empty()){
        bool f = true;
        auto b = q.front(); q.pop();
        rep(i,4) rep(j,4){
            auto d = b;
            if(d[i][j] > 0){
                f = false;
                d[i][j]++;
                if(d[i][j] == 5) process(d,i,j);
            }else{
                d[i][j] = 1;
            }
            if(dp[b] + 1 > 5) continue;
            if(!dp.count(d)){
                dp[d] = dp[b] + 1;
                q.emplace(d);
            }else{
                if(dp[d] > dp[b] + 1){
                    dp[d] = dp[b] + 1;
                    q.emplace(d);
                }
            }
        }
        if(f){
            cout << dp[b] << endl;
            return 0;
        }
    }
    cout << -1 << endl;
}
accuracy: 1
time_ms: 420
memory_kb: 27952
final_rank: 20

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}

typedef array<array<int,4>,4> F;

int dx[]={1,-1,0,0};
int dy[]={0,0,1,-1};

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    F a;
    for(int i=0;i<4;i++){
        for(int j=0;j<4;j++){
            cin >> a[i][j];
        }
    }
    queue<F> q;
    q.push(a);
    map<F,int> mp;
    mp[a] = 0;
    int res = -1;
    auto get_nxt=[](F cur,int x,int y)->F{
        vector<pair<pair<int,int>,int>> v;
        cur[x][y]++;
        if(cur[x][y] >= 5){
            cur[x][y] = 0;
            for(int i=0;i<4;i++){
                v.push_back({{x,y},i});
            }
        }
        while(v.size()){
            vector<pair<pair<int,int>,int>> nv;
            for(auto t:v){
                x = t.first.first, y = t.first.second;
                int k = t.second;
                if(cur[x][y] > 0){
                    cur[x][y]++;
                }
                else{
                    x+=dx[k];
                    y+=dy[k];
                    if(0<=x and x<4 and 0<=y and y<4){
                        nv.push_back({{x,y},k});
                    }
                }
            }
            for(int i=0;i<4;i++){
                for(int j=0;j<4;j++){
                    if(cur[i][j]>=5){
                        cur[i][j]=0;
                        for(int k=0;k<4;k++){
                            nv.push_back({{i,j},k});
                        }
                    }
                }
            }
            swap(v,nv);
        }
        return cur;
    };
    while(q.size()){
        F p = q.front(); q.pop();
        bool ok=true;
        for(int i=0;i<4;i++){
            for(int j=0;j<4;j++){
                if(p[i][j]>0)ok=false;
            }
        }
        int pre = mp[p];
        if(ok){
            res = pre;
            break;
        }
        if(pre < 5){
            for(int i=0;i<4;i++){
                for(int j=0;j<4;j++){
                    auto nxt = get_nxt(p,i,j);
                    if(mp.find(nxt) == mp.end()){
                        mp[nxt] = pre + 1;
                        q.push(nxt);
                    }
                }
            }
        }
    }
    cout << res << endl;
}
accuracy: 1
time_ms: 60
memory_kb: 10772
final_rank: 12

code_snippet: #include <iostream>
#include <vector>
#include <tuple>
#include <queue>
#include <map>

template <class T>
using MinHeap = std::priority_queue<T, std::vector<T>, std::greater<T>>;

using namespace std;
using lint = long long;

constexpr int INF = 1 << 30;
const vector<pair<int, int>> dxys{{0, 1}, {0, -1}, {1, 0}, {-1, 0}};

lint enc(const vector<vector<int>>& xss) {
    lint ret = 0;
    lint d = 1;
    for (int x = 0; x < 4; ++x) {
        for (int y = 0; y < 4; ++y) {
            ret += xss[x][y] * d;
            d *= 5;
        }
    }
    return ret;
}

vector<vector<int>> dec(lint b) {
    auto ret = vector(4, vector(4, 0));
    for (int x = 0; x < 4; ++x) {
        for (int y = 0; y < 4; ++y) {
            ret[x][y] = b % 5;
            b /= 5;
        }
    }
    return ret;
}

void sim(vector<vector<int>>& xss) {
    vector<tuple<int, int, int>> drops;
    for (int x = 0; x < 4; ++x) {
        for (int y = 0; y < 4; ++y) {
            if (xss[x][y] >= 5) {
                xss[x][y] = 0;
                for (int i = 0; i < 4; ++i) {
                    drops.emplace_back(x, y, i);
                }
            }
        }
    }

    while (!drops.empty()) {
        vector<tuple<int, int, int>> ndrops;

        for (auto [x, y, i] : drops) {
            auto [dx, dy] = dxys[i];
            int nx = x + dx,
                ny = y + dy;

            if (nx < 0 || 4 <= nx ||
                ny < 0 || 4 <= ny) continue;

            if (xss[nx][ny] != 0) {
                ++xss[nx][ny];
            } else {
                ndrops.emplace_back(nx, ny, i);
            }
        }

        swap(drops, ndrops);

        for (int x = 0; x < 4; ++x) {
            for (int y = 0; y < 4; ++y) {
                if (xss[x][y] >= 5) {
                    xss[x][y] = 0;
                    for (int i = 0; i < 4; ++i) {
                        drops.emplace_back(x, y, i);
                    }
                }
            }
        }
    }
}

void solve() {
    map<lint, int> dp;
    MinHeap<pair<int, lint>> que;

    {
        auto xss = vector(4, vector(4, 0));
        for (auto& xs : xss) {
            for (auto& x : xs) cin >> x;
        }
        lint b = enc(xss);

        dp[b] = 0;
        que.emplace(dp[b], b);
    }

    while (!que.empty()) {
        auto [d, b] = que.top();
        que.pop();
        if (dp[b] < d) continue;

        auto xss = dec(b);
        for (int x = 0; x < 4; ++x) {
            for (int y = 0; y < 4; ++y) {
                auto nxss = xss;
                if (++nxss[x][y] == 5) sim(nxss);

                lint nb = enc(nxss);
                if (!dp.count(nb)) dp[nb] = INF;

                if (dp[nb] <= d + 1) continue;
                dp[nb] = d + 1;
                if (dp[nb] < 5) que.emplace(dp[nb], nb);
            }
        }
    }

    cout << (dp.count(0) ? dp[0] : -1) << "\n";
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    solve();

    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 6308
final_rank: 9

code_snippet: #include <iostream>
#include <vector>
#include <tuple>
#include <queue>
#include <map>

template <class T>
using MinHeap = std::priority_queue<T, std::vector<T>, std::greater<T>>;

using namespace std;
using lint = long long;

constexpr int INF = 1 << 30;
const vector<pair<int, int>> dxys{{0, 1}, {0, -1}, {1, 0}, {-1, 0}};

lint enc(const vector<vector<int>>& xss) {
    lint ret = 0;
    lint d = 1;
    for (int x = 0; x < 4; ++x) {
        for (int y = 0; y < 4; ++y) {
            ret += xss[x][y] * d;
            d *= 5;
        }
    }
    return ret;
}

vector<vector<int>> dec(lint b) {
    auto ret = vector(4, vector(4, 0));
    for (int x = 0; x < 4; ++x) {
        for (int y = 0; y < 4; ++y) {
            ret[x][y] = b % 5;
            b /= 5;
        }
    }
    return ret;
}

void sim(vector<vector<int>>& xss) {
    // for (const auto& xs : xss) {
    //     for (auto x : xs) cerr << x;
    //     cerr << "\n";
    // }
    // cerr << "|\nV\n";

    vector<tuple<int, int, int>>
        drops;
    for (int x = 0; x < 4; ++x) {
        for (int y = 0; y < 4; ++y) {
            if (xss[x][y] >= 5) {
                xss[x][y] = 0;
                for (int i = 0; i < 4; ++i) {
                    drops.emplace_back(x, y, i);
                }
            }
        }
    }

    while (!drops.empty()) {
        vector<tuple<int, int, int>> ndrops;

        for (auto [x, y, i] : drops) {
            auto [dx, dy] = dxys[i];
            int nx = x + dx,
                ny = y + dy;

            if (nx < 0 || 4 <= nx ||
                ny < 0 || 4 <= ny) continue;

            if (xss[nx][ny] != 0) {
                ++xss[nx][ny];
            } else {
                ndrops.emplace_back(nx, ny, i);
            }
        }

        swap(drops, ndrops);

        for (int x = 0; x < 4; ++x) {
            for (int y = 0; y < 4; ++y) {
                if (xss[x][y] >= 5) {
                    xss[x][y] = 0;
                    for (int i = 0; i < 4; ++i) {
                        drops.emplace_back(x, y, i);
                    }
                }
            }
        }
    }

    // for (const auto& xs : xss) {
    //     for (auto x : xs) cerr << x;
    //     cerr << "\n";
    // }
    // cerr << "\n";
}

void solve() {
    map<lint, int> dp;
    MinHeap<pair<int, lint>> que;

    {
        auto xss = vector(4, vector(4, 0));
        for (auto& xs : xss) {
            for (auto& x : xs) cin >> x;
        }
        lint b = enc(xss);

        dp[b] = 0;
        que.emplace(dp[b], b);
    }

    while (!que.empty()) {
        auto [d, b] = que.top();
        que.pop();
        if (dp[b] < d) continue;

        auto xss = dec(b);
        for (int x = 0; x < 4; ++x) {
            for (int y = 0; y < 4; ++y) {
                auto nxss = xss;
                if (++nxss[x][y] == 5) sim(nxss);

                lint nb = enc(nxss);
                if (!dp.count(nb)) dp[nb] = INF;

                if (dp[nb] <= d + 1) continue;
                dp[nb] = d + 1;
                if (dp[nb] < 5) que.emplace(dp[nb], nb);
            }
        }
    }

    cout << (dp.count(0) ? dp[0] : -1) << "\n";
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    solve();

    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 6320
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;
using PII = pair<ll, ll>;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()
#define POPCOUNT(x) __builtin_popcount(x)
template <typename T> void chmin(T &a, const T &b) { a = min(a, b); }
template <typename T> void chmax(T &a, const T &b) { a = max(a, b); }

const ll INF = 1LL << 60;

struct FastIO {
    FastIO() {
        cin.tie(0);
        ios::sync_with_stdio(0);
    }
} fastiofastio;

using T = tuple<int, int, int>;

int bubble[4][4];
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};

void push(int x, int y) {
    vector<T> drop;
    bubble[y][x]++;
    if (bubble[y][x] < 5)
        return;
    bubble[y][x] = 0;
    for (int d = 0; d < 4; d++)
        drop.emplace_back(x, y, d);
    while (!drop.empty()) {
        vector<T> nxt;
        for (T t : drop) {
            int X = get<0>(t);
            int Y = get<1>(t);
            int D = get<2>(t);
            X += dx[D];
            Y += dy[D];
            if (0 > X || X >= 4 || 0 > Y || Y >= 4)
                continue;
            if (bubble[Y][X] == 0) {
                nxt.emplace_back(X, Y, D);
            } else {
                bubble[Y][X]++;
            }
        }
        for (int Y = 0; Y < 4; Y++) {
            for (int X = 0; X < 4; X++) {
                if (bubble[Y][X] < 5)
                    continue;
                bubble[Y][X] = 0;
                for (int D = 0; D < 4; D++) {
                    nxt.emplace_back(X, Y, D);
                }
            }
        }
        drop = nxt;
    }
}

int ans = 1 << 30;

void dfs(int k) {
    bool ok = 1;
    for (int y = 0; y < 4; y++) {
        for (int x = 0; x < 4; x++) {
            if (bubble[y][x] != 0) {
                ok = 0;
                break;
            }
        }
    }
    if (ok)
        ans = min(ans, k);
    if (k == 5)
        return;
    int save[4][4];
    for (int y = 0; y < 4; y++) {
        for (int x = 0; x < 4; x++) {
            memcpy(save, bubble, sizeof(save));
            push(x, y);
            dfs(k + 1);
            memcpy(bubble, save, sizeof(save));
        }
    }
}

int main() {
    for (int y = 0; y < 4; y++) {
        for (int x = 0; x < 4; x++)
            cin >> bubble[y][x];
    }
    dfs(0);
    if (ans == 1 << 30)
        cout << -1 << endl;
    else
        cout << ans << endl;
}
accuracy: 1
time_ms: 400
memory_kb: 3472
final_rank: 4