Problem:
Problem D: Fissure Puzzle Easy
Problem
$N \times N$個のマスから成るグリッドがある。最初すべてのマスは白色である。以下の手順に従って黒色のマスを増やしていく。
上から偶数番目かつ、左から偶数番目であるマスの中で、白色のマスを1つ選ぶ。選んだマスは黒色に変化する。さらに、そのマスの上下左右それぞれの方向について、隣接している白色のマスも連鎖的に黒色に変化する。この連鎖はその方向に白色のマスが存在しなくなるまで続く。(以下に例を示す)
□□□□□□□□□
□□□□□□□□□
□□□□□□□□□
□□□□□□□□□
□□□□□□□□□
□□□□□□□□□
□□□□□□□□□
□□□□□□□□□
□□□□□□□□□
↓上から4番目、左から6番目を選ぶ
□□□□□■□□□
□□□□□■□□□
□□□□□■□□□
■■■■■■■■■
□□□□□■□□□
□□□□□■□□□
□□□□□■□□□
□□□□□■□□□
□□□□□■□□□
↓上から2番目、左から2番目を選ぶ
□■□□□■□□□
■■■■■■□□□
□■□□□■□□□
■■■■■■■■■
□□□□□■□□□
□□□□□■□□□
□□□□□■□□□
□□□□□■□□□
□□□□□■□□□
↓上から6番目、左から8番目を選ぶ
□■□□□■□□□
■■■■■■□□□
□■□□□■□□□
■■■■■■■■■
□□□□□■□■□
□□□□□■■■■
□□□□□■□■□
□□□□□■□■□
□□□□□■□■□
あなたは上から$i$番目で左から$j$番目のマスの色が$A_{i,j}$であるグリッドを作りたい。マスを選ぶ最小の回数を求めよ。
Input
入力は以下の形式で与えられる。
$N$
$A_{1,1}$ $A_{1,2}$ ... $A_{1,N}$
$A_{2,1}$ $A_{2,2}$ ... $A_{2,N}$
...
$A_{N,1}$ $A_{N,2}$ ... $A_{N,N}$
$A_{i,j}$が'o'であるときは上から$i$番目、左から$j$番目のマスが白色であることを表し、'x'のときは黒色のマスであることを表す。
Constraints
入力は以下の条件を満たす。
$3 \le N \le 127$
$N$は奇数である
$A_{i,j}$は'o'か'x'である
必ず作ることができるような入力しか与えられない
Output
1行目にマスを選ぶ回数の最小値を出力する。
Sample Input 1
5
oxooo
oxooo
oxooo
xxxxx
oxooo
Sample Output 1
1
Sample Input 2
9
oxoooooxo
oxxxxxxxx
oxoooooxo
xxxxxxxxx
oxoxooooo
oxxxxxxxx
oxoxoxooo
oxoxxxxxx
oxoxoxooo
Sample Output 2
4

Submitted solutions:

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <string>
#include <vector>
#include <set>
#include <cstdlib>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

struct Sum2D {
	vector<vector<ll>> b;
	Sum2D() {};
	Sum2D(const vector<vector<ll>>& a) {
		int H = a.size(), W = a[0].size();
		b = a;
		for(int i = 0; i < H; i++)
		for(int j = 0; j < W - 1; j++) b[i][j + 1] += b[i][j];
		for(int j = 0; j < W; j++)
		for(int i = 0; i < H - 1; i++) b[i + 1][j] += b[i][j];
	}
	// ?????????
	ll sum(int x1, int y1, int x2, int y2) {
		ll ret = b[y2][x2];
		if(y1 - 1 >= 0) ret -= b[y1 - 1][x2];
		if(x1 - 1 >= 0) ret -= b[y2][x1 - 1];
		if(y1 - 1 >= 0 && x1 - 1 >= 0) ret += b[y1 - 1][x1 - 1];
		return ret;
	}
};
Sum2D S;

//D
int N;

bool in(int x, int y) {
	return 0 <= x && x < N && 0 <= y && y < N;
}

string A[128];
int dp[64][64][64][64];
int dx[4] = { 1, 0, -1, 0 }, dy[4] = { 0, 1, 0, -1 };

vector<int> cross[128];

int conv(int x1, int y1, int x2, int y2) {
	int ret = x1;
	ret = ret * 128 + y1;
	ret = ret * 128 + x2;
	ret = ret * 128 + y2;
	return ret;
}

map<int, int> dpm;

int f(int x1, int y1, int x2, int y2) {
	if(x2 < x1 || y2 < y1) return 0;
	int hash = conv(x1, y1, x2, y2);
	if(dpm.count(hash)) return dpm[hash];
	//if(dp[x1][y1][x2][y2] >= 0) return dp[x1][y1][x2][y2];
	//int& d = dp[x1][y1][x2][y2];
	int H = y2 - y1 + 1, W = x2 - x1 + 1;
	if(S.sum(x1, y1, x2, y2) == 0) return 0;
	int d = 1000;
	for(int y = y1; y <= y2; y++) {
		for(auto x : cross[y]) {
			if(x1 <= x && x <= x2) {
				if(S.sum(x1, y, x2, y) != W) continue;
				if(S.sum(x, y1, x, y2) != H) continue;
				int sum = 1;
				sum += f(x1, y1, x - 1, y - 1);
				sum += f(x + 1, y1, x2, y - 1);
				sum += f(x1, y + 1, x - 1, y2);
				sum += f(x + 1, y + 1, x2, y2);
				d = min(d, sum);
			}
		}
	}
	return dpm[hash] = d;
}

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

	cin >> N;
	vector<vector<ll>> b(N);
	for(int i = 0; i < N; i++) {
		cin >> A[i];
		for(int j = 0; j < N; j++) {
			b[i].push_back(A[i][j] == 'x');
		}
	}
	S = Sum2D(b);
	for(int y = 0; y < N; y++) {
		for(int x = 0; x < N; x++) {
			if(A[y][x] == 'o') continue;
			bool ok = true;
			for(int k = 0; k < 4; k++) {
				int nx = x + dx[k], ny = y + dy[k];
				if(in(nx, ny) && A[ny][nx] == 'o') {
					ok = false;
					break;
				}
			}
			if(ok) cross[y].push_back(x);
		}
	}
	memset(dp, -1, sizeof dp);
	cout << f(0, 0, (N - 1), (N - 1)) << endl;
}
accuracy: 1
time_ms: 20
memory_kb: 68876
final_rank: 2

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <string>
#include <vector>
#include <set>
#include <cstdlib>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

struct Sum2D {
	vector<vector<ll>> b;
	Sum2D() {};
	Sum2D(const vector<vector<ll>>& a) {
		int H = a.size(), W = a[0].size();
		b = a;
		for(int i = 0; i < H; i++)
		for(int j = 0; j < W - 1; j++) b[i][j + 1] += b[i][j];
		for(int j = 0; j < W; j++)
		for(int i = 0; i < H - 1; i++) b[i + 1][j] += b[i][j];
	}
	// ?????????
	ll sum(int x1, int y1, int x2, int y2) {
		ll ret = b[y2][x2];
		if(y1 - 1 >= 0) ret -= b[y1 - 1][x2];
		if(x1 - 1 >= 0) ret -= b[y2][x1 - 1];
		if(y1 - 1 >= 0 && x1 - 1 >= 0) ret += b[y1 - 1][x1 - 1];
		return ret;
	}
};
Sum2D S;

//D
int N;

bool in(int x, int y) {
	return 0 <= x && x < N && 0 <= y && y < N;
}

string A[128];
int dp[64][64][64][64];
int dx[4] = { 1, 0, -1, 0 }, dy[4] = { 0, 1, 0, -1 };

vector<int> cross[128];

int conv(int x1, int y1, int x2, int y2) {
	int ret = x1;
	ret = ret * 128 + y1;
	ret = ret * 128 + x2;
	ret = ret * 128 + y2;
	return ret;
}

map<int, int> dpm;

int f(int x1, int y1, int x2, int y2) {
	if(x2 < x1 || y2 < y1) return 0;
	int hash = conv(x1, y1, x2, y2);
	if(dpm.count(hash)) return dpm[hash];
	//if(dp[x1][y1][x2][y2] >= 0) return dp[x1][y1][x2][y2];
	//int& d = dp[x1][y1][x2][y2];
	int H = y2 - y1 + 1, W = x2 - x1 + 1;
	int d = 1000;
	bool exist = false;
	for(int y = y1; y <= y2; y++) {
		for(auto x : cross[y]) {
			if(x1 <= x && x <= x2) {
				if(S.sum(x1, y, x2, y) != W) continue;
				if(S.sum(x, y1, x, y2) != H) continue;
				int sum = 1;
				sum += f(x1, y1, x - 1, y - 1);
				sum += f(x + 1, y1, x2, y - 1);
				sum += f(x1, y - 1, x - 1, y2);
				sum += f(x + 1, y + 1, x2, y2);
				d = min(d, sum);
				exist = true;
			}
		}
	}
	if(!exist) d = 0;
	return dpm[hash] = d;
}

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

	cin >> N;
	vector<vector<ll>> b(N);
	for(int i = 0; i < N; i++) {
		cin >> A[i];
		for(int j = 0; j < N; j++) {
			b[i].push_back(A[i][j] == 'x');
		}
	}
	S = Sum2D(b);
	for(int y = 0; y < N; y++) {
		for(int x = 0; x < N; x++) {
			if(A[y][x] == 'o') continue;
			bool ok = true;
			for(int k = 0; k < 4; k++) {
				int nx = x + dx[k], ny = y + dy[k];
				if(in(nx, ny) && A[ny][nx] == 'o') {
					ok = false;
					break;
				}
			}
			if(ok) cross[y].push_back(x);
		}
	}
	memset(dp, -1, sizeof dp);
	cout << f(0, 0, (N - 1), (N - 1)) << endl;
}
accuracy: 0.11764705882352941
time_ms: 20
memory_kb: 68712
final_rank: 4

code_snippet: #include<iostream>
#include<vector>
#include<string>
#include<algorithm>	
#include<map>
#include<set>
#include<utility>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<cstdio>
#include<sstream>
#include<iomanip>
#include<assert.h>
#define loop(i,a,b) for(int i=a;i<b;i++) 
#define rep(i,a) loop(i,0,a)
#define pb push_back
#define all(in) in.begin(),in.end()
#define shosu(x) fixed<<setprecision(x)
using namespace std;
//kaewasuretyuui
typedef long long ll;
typedef int Def;
typedef pair<Def,Def> pii;
typedef vector<Def> vi;
typedef vector<vi> vvi;
typedef vector<pii> vp;
typedef vector<vp> vvp;
typedef vector<string> vs;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef pair<Def,pii> pip;
typedef vector<pip>vip;
//#define mt make_tuple
//typedef tuple<double,int,double> tp;
//typedef vector<tp> vt;
template<typename A,typename B>bool cmin(A &a,const B &b){return a>b?(a=b,true):false;}
template<typename A,typename B>bool cmax(A &a,const B &b){return a<b?(a=b,true):false;}
const double PI=acos(-1);
const double EPS=1e-7;
Def inf=sizeof(Def)==sizeof(long long)?2e18:1e9;
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
vs in;
int f(int a,int b,int c,int d){
//	cout<<a<<" "<<b<<" "<<c<<" "<<d<<endl;
	bool H=false;
	loop(i,a,c)loop(j,b,d)if(in[i][j]=='x')H=true;
	if(!H)return 0;
	vi ta,yo;
	loop(i,a,c){
		bool h=true;
		loop(j,b,d)if(in[i][j]=='o')h=false;
		if(h)yo.pb(i);
	}
	loop(i,b,d){
		bool h=true;
		loop(j,a,c)if(in[j][i]=='o')h=false;
		if(h)ta.pb(i);
	}
	int out=0;
//	cout<<a<<" "<<b<<" "<<c<<" "<<d<<endl;
//	cout<<yo.size()<<" "<<ta.size()<<endl;
	rep(i,yo.size())rep(j,ta.size())
		out=max(out,f(a,b,yo[i],ta[j])+f(a,ta[j]+1,yo[i],d)+f(yo[i]+1,b,c,ta[j])+f(yo[i]+1,ta[j]+1,c,d)+1);
	return out;
}
int main(){
	int n;
	cin>>n;
	in=vs(n);
	rep(i,n)cin>>in[i];
	cout<<f(0,0,n,n)<<endl;
}
accuracy: 1
time_ms: 40
memory_kb: 3196
final_rank: 1

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <string>
#include <vector>
#include <set>
#include <cstdlib>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

//D
int N;

bool in(int x, int y) {
	return 0 <= x && x < N && 0 <= y && y < N;
}

string A[127];
string B[64];
int dp[64][64][64][64];
int dx[4] = { 1, 0, -1, 0 }, dy[4] = { 0, 1, 0, -1 };

vector<int> cross[64];

int f(int x1, int y1, int x2, int y2) {
	if(x2 < x1 || y2 < y1) return 0;
	if(dp[x1][y1][x2][y2] >= 0) return dp[x1][y1][x2][y2];
	int& d = dp[x1][y1][x2][y2];
	d = 1000;
	for(int y = y1; y <= y2; y++) {
		for(auto x : cross[y]) {
			if(x1 <= x && x <= x2) {
				int sum = 1;
				sum += f(x1, y1, x, y);
				sum += f(x, y1, x2, y);
				sum += f(x1, y, x, y2);
				sum += f(x, y, x2, y2);
				d = min(d, sum);
			}
		}
	}
	if(d == 1000) d = 0;
	return d;
}

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

	cin >> N;
	for(int i = 0; i < N; i++) {
		cin >> A[i];
		if(i % 2 == 0) continue;
		for(int j = 0; j < N; j++) {
			if(j % 2 == 0) continue;
			B[i / 2] += A[i][j];
		}
	}
	for(int y = 0; y < N; y++) {
		for(int x = 0; x < N; x++) {
			if(A[y][x] == 'o') continue;
			bool ok = true;
			for(int k = 0; k < 4; k++) {
				int nx = x + dx[k], ny = y + dy[k];
				if(in(nx, ny) && A[ny][nx] == 'o') {
					ok = false;
					break;
				}
			}
			if(ok) cross[y / 2].push_back(x / 2);
		}
	}
	memset(dp, -1, sizeof dp);
	cout << f(0, 0, (N - 1) / 2, (N - 1) / 2) << endl;
}
accuracy: 0.08823529411764706
time_ms: 20
memory_kb: 68704
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define pb push_back

const int N = 64;
const int INF = 19191919;

int n;
string a[128];

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

bool is_candidate(int lx, int ly, int rx, int ry, int X, int Y)
{
    if(a[Y][X]!='x') return false;
    bool ret = true;
    for(int i=lx; i<=rx; ++i) ret &= (a[Y][i]=='x');
    for(int i=ly; i<=ry; ++i) ret &= (a[i][X]=='x');
    return ret;
}

int f(int lx, int ly, int rx, int ry)
{
    if(dp[lx/2][ly/2][rx/2][ry/2]<INF) return dp[lx/2][ly/2][rx/2][ry/2];

    // printf("CALL %d %d %d %d\n", lx,ly,rx,ry);

    bool is_empty=true;
    for(int i=ly; i<=ry; ++i)for(int j=lx; j<=rx; ++j)if(a[i][j]=='x') is_empty = false;
    if(is_empty) return 0;

    int ret = INF;
    for(int i=ly+1; i<ry; i+=2)for(int j=lx+1; j<rx; j+=2)
    {
        // ???????????????????£?
        if(is_candidate(lx,ly,rx,ry,j,i))
        {
            // printf("  !CANDIDATE %d %d\n", i,j);
            ret = min(ret, 1+f(lx,ly,j-1,i-1)+f(j+1,ly,rx,i-1)+f(lx,i+1,j-1,ry)+f(j+1,i+1,rx,ry));
        }
    }

    return dp[lx/2][ly/2][rx/2][ry/2] = ret;
}

int main()
{
    rep(i,N)rep(j,N)rep(k,N)rep(l,N) dp[i][j][k][l]=INF;

    cin >>n;
    rep(i,n) cin >>a[i];
    cout << f(0,0,n-1,n-1) << endl;
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 68708
final_rank: 3