Problem:
庭園 2 (Garden 2)
問題文
JOI 庭園は縦
N
行，横
N
列のマス目状に区切られた正方形の形をしている．
上から
i
行目 (
1 ≦ i ≦ N
)，左から
j
列目 (
1 ≦ j ≦ N
) のマスは区画
(i, j)
と呼ばれている．
JOI 庭園は土壌にあまり恵まれていないため，各区画には特定の
1
種類の色の花を，
最大
1
本しか植えることができない．
具体的には，区画
(i, j)
には
A
i, j
=
R
のとき赤，
A
i, j
=
Y
のとき黄，
A
i, j
=
B
のとき青の色の花を最大
1
本しか植えることができない．
ここで，この庭園の管理者である K 理事長は，航空写真を撮った時の見栄えを良くするため，次の手順で花を植えようと思っている．
大きさ
を表す整数
r
を決める．ただし
0 ≦ r ≦ (N-1) ÷ 2
を満たさなければならない．
中心
を表す区画
(x, y)
を決める．ただし
r+1 ≦ x ≦ N-r
，
r+1 ≦ y ≦ N-r
を満たさなければならない．
色
c
0
, c
1
, c
2
, …, c
r
をそれぞれ赤・黄・青の中から選んで決める．
それぞれの区画
(x', y')
について，
d = |x'-x| + |y'-y|
に応じて以下の規則で花を植える．ただし，
|t|
は
t
の絶対値を表す．
d ≦ r
であるならば，区画
(x', y')
には色
c
d
の花を植える．
d > r
であるならば，区画
(x', y')
には花を植えない．
庭園の大きさ，各区画に植えることができる花の色の情報が与えられたとき，K 理事長が植えることができる花の数の最大値を求めるプログラムを作成せよ．
制約
3 ≦ N ≦ 3 500
．
A
i, j
は
R
，
Y
，
B
のいずれかである (
1 ≦ i ≦ N, 1 ≦ j ≦ N
)．
N
は整数である．
入力
入力は以下の形式で与えられる．
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
出力
K 理事長が植えることができる花の数の最大値を
1
行で出力せよ．
入出力例
入力例 1
3
RYR
YBY
BYY
出力例 1
5
r = 1
，
(x, y) = (2, 2)
とし，
c
0
として青，
c
1
として黄を選ぶと，下図のように
5
本の花を植えることができる．ただし，背景色は各区画に植えることができる花の色を示している．
6
本以上の花を植える方法は存在しないため，
5
を出力する．
入力例 2
9
YYRYBBBYR
BYYRRBYBB
RBRRBRBBY
RYRBRYRBR
YYBRYYYRB
RRYBRYRBR
RBYRBRBRB
BRYYRBBBR
RBBBYBRRY
出力例 2
25
r = 3
，
(x, y) = (5, 6)
とし，
c
0
として黄，
c
1
として黄，
c
2
として赤，
c
3
として青を選ぶと，下図のように
25
本の花を植えることができる．ただし，背景色は各区画に植えることができる花の色を示している．
26
本以上の花を植える方法は存在しないため，
25
を出力する．
入力例 3
6
RBYRBY
BYRBYR
YRBYRB
RBYRBY
BYRBYR
YRBYRB
出力例 3
1
入力例 4
20
RRRRRRRRRRRRRRRRRRRR
RRRRRRRRRRRRRRRRRRRR
RRRRBRRRRRRRRRRRRYRR
RRRRRRRRRRRRRRRRRRRR
RRRRRRRRRRRRRRRRRRRR
RRRRRRRRRRRRRRRRRRRR
RRRRRRRRRRRYRRRRRRRR
RRRRRRRRRRRRRRRRRRRR
RRRRRRRRRRRRRRRRRRRR
RRRRRRRRRRRRRRRRRRRR
RRRRRRRRRRRRRRRRRRRR
RRRRRYRRRRRRRRRRRRRR
RRRRRRRRRRRRRRRRRRRR
RRRRRRRRRRRRRRRRRRRR
RRRRRRRRRRRRRRRRRRBR
RRRRRRRRRRRRRRRRRRRR
RRRRRRRRRRRRRRRRRRRR
RRRRRRRRRRRRRRRRRRRR
RRRRRRRRRRRRRRRRRRRR
RRRRRRRRRRRRRRRRRRRR
出力例 4
85
入力例 5
10
RRRRRRRRRR
RYRRRRRRRR
RRRRYRRRRR
RBRRRRRRRR
RRRRRRRRYR
RBRRRRRRRR
RRRRBRRRRR
RBRRRRRRRR
RRRRRRRRYR
RRRRRRRRRR
出力例 5
25
情報オリンピック日本委員会
作 『第 23 回日本情報オリンピック (JOI 2023/2024) 二次予選競技課題』

Submitted solutions:

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

constexpr int MAXN = 3505;

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

    int N;
    cin >> N;

    vector<string> A(N + 2, string(N + 2, '#')); // 1-indexed, 周囲を番兵で埋める

    for (int r = 1; r <= N; r++) {
        string s;
        cin >> s;
        for (int c = 1; c <= N; c++) {
            A[r][c] = s[c - 1];
        }
    }

    vector<vector<int>> dp1(N + 2, vector<int>(N + 2, 0));
    vector<vector<int>> dp2(N + 2, vector<int>(N + 2, 0));
    vector<vector<int>> dp3(N + 2, vector<int>(N + 2, 0));
    vector<vector<int>> dp4(N + 2, vector<int>(N + 2, 0));

    // 左上
    for (int r = 1; r <= N; r++) {
        for (int c = 1; c <= N; c++) {
            if (A[r][c] != A[r + 1][c - 1]) dp1[r][c] = 0;
            else dp1[r][c] = min(dp1[r - 1][c], dp1[r][c - 1]) + 1;
        }
    }

    // 左下
    for (int r = N; r > 0; r--) {
        for (int c = 1; c <= N; c++) {
            if (A[r][c] != A[r + 1][c + 1]) dp2[r][c] = 0;
            else dp2[r][c] = min(dp2[r + 1][c], dp2[r][c - 1]) + 1;
        }
    }

    // 右上
    for (int r = 1; r <= N; r++) {
        for (int c = N; c >= 1; c--) {
            if (A[r][c] != A[r - 1][c - 1]) dp3[r][c] = 0;
            else dp3[r][c] = min(dp3[r - 1][c], dp3[r][c + 1]) + 1;
        }
    }

    // 右下
    for (int r = N; r > 0; r--) {
        for (int c = N; c >= 1; c--) {
            if (A[r][c] != A[r - 1][c + 1]) dp4[r][c] = 0;
            else dp4[r][c] = min(dp4[r + 1][c], dp4[r][c + 1]) + 1;
        }
    }

    int ans = 0;
    for (int r = 2; r < N; r++) {
        for (int c = 2; c < N; c++) {
            int t = dp1[r - 1][c];
            t = min(t, dp2[r][c - 1]);
            t = min(t, dp3[r][c + 1]);
            t = min(t, dp4[r + 1][c]);
            t = min({t, r - 1, c - 1, N - r, N - c});
            ans = max(ans, t);
        }
    }

    cout << 1 + 2 * ans * (ans + 1) << "\n";
    return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 207616
final_rank: 3

code_snippet: // AOJ #778 Garden 2
// 2025.3.4

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

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {  // 整数の入力
	int n = 0, c = gc();
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

void Cins(char t[]) { // 文字列の入力　スペース以下の文字で入力終了
    char *s = t;
	do *s = gc();
	while (*s++ > ' ');
	*(s-1) = 0;
}

void Cout(int n) { // 整数の表示（出力）
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int r = 0; while (n) b[r++] = n % 10 + '0', n /= 10;
		while (r--) pc(b[r]);
	}
	pc('\n');
}

void chmin(int &a, int b) { if (a > b) a = b; }
void chmax(int &a, int b) { if (a < b) a = b; }

const int MAXN = 3505;
int dp1[MAXN][MAXN];
int dp2[MAXN][MAXN];
int dp3[MAXN][MAXN];
int dp4[MAXN][MAXN];
char  A[MAXN][MAXN];

int main() {
    int N = Cin();
	for (int r = 1; r <= N; r++) Cins(A[r]+1);

	for (int r = 1; r <= N; r++) {
		for (int c = 1; c <= N; c++) {
			if (A[r][c] != A[r + 1][c - 1]) dp1[r][c] = 0;
			else dp1[r][c] = min(dp1[r - 1][c], dp1[r][c - 1]) + 1;
		}
	}

	for (int r = N; r > 0; r--) {
		for (int c = 1; c <= N; c++) {
			if (A[r][c] != A[r + 1][c + 1]) dp2[r][c] = 0;
			else dp2[r][c] = min(dp2[r + 1][c], dp2[r][c - 1]) + 1;
		}
	}

	for (int r = 1; r <= N; r++) {
		for (int c = N; c >= 1; c--) {
			if (A[r][c] != A[r - 1][c - 1]) dp3[r][c] = 0;
			else dp3[r][c] = min(dp3[r - 1][c], dp3[r][c + 1]) + 1;
		}
	}

	for (int r = N; r > 0; r--) {
		for (int c = N; c >= 1; c--) {
			if (A[r][c] != A[r - 1][c + 1]) dp4[r][c] = 0;
			else dp4[r][c] = min(dp4[r + 1][c], dp4[r][c + 1]) + 1;
		}
	}
	int ans = 0;
	for (int r = 2; r < N; r++) {
		for (int c = 2; c < N; c++) {
			int t = dp1[r - 1][c];
			chmin(t, dp2[r][c - 1]);
			chmin(t, dp3[r][c + 1]);
			chmin(t, dp4[r + 1][c]);
			chmin(t, min({ r - 1, c - 1, N - r, N - c }));
			chmax(ans, t);
		}
	}
	Cout(1+2*ans*(ans+1));
	return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 207328
final_rank: 1

code_snippet: // AOJ #778 Garden 2
// 2025.3.4

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

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {  // 整数の入力
	int n = 0, c = gc();
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

void Cins(char t[]) { // 文字列の入力　スペース以下の文字で入力終了
    char *s = t;
	do *s = gc();
	while (*s++ > ' ');
	*(s-1) = 0;
}

void Cout(int n) { // 整数の表示（出力）
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int r = 0; while (n) b[r++] = n % 10 + '0', n /= 10;
		while (r--) pc(b[r]);
	}
	pc('\n');
}

void chmin(int &a, int b) { if (a > b) a = b; }
void chmax(int &a, int b) { if (a < b) a = b; }

const int MAXN = 3505;
int dp1[MAXN][MAXN];
int dp2[MAXN][MAXN];
int dp3[MAXN][MAXN];
int dp4[MAXN][MAXN];
char  A[MAXN][MAXN];

int main() {
    int N = Cin();
	for (int r = 1; r <= N; r++) Cins(A[r]+1);

	for (int r = 1; r <= N; r++) {
		for (int c = 1; c <= N; c++) {
			if (A[r][c] != A[r + 1][c - 1]) dp1[r][c] = 0;
			if (A[r][c] == A[r + 1][c - 1]) dp1[r][c] = min(dp1[r - 1][c], dp1[r][c - 1]) + 1;
		}
	}

	for (int r = N; r > 0; r--) {
		for (int c = 1; c <= N; c++) {
			if (A[r][c] != A[r + 1][c + 1]) dp2[r][c] = 0;
			if (A[r][c] == A[r + 1][c + 1]) dp2[r][c] = min(dp2[r + 1][c], dp2[r][c - 1]) + 1;
		}
	}

	for (int r = 1; r <= N; r++) {
		for (int c = N; c >= 1; c--) {
			if (A[r][c] != A[r - 1][c - 1]) dp3[r][c] = 0;
			if (A[r][c] == A[r - 1][c - 1]) dp3[r][c] = min(dp3[r - 1][c], dp3[r][c + 1]) + 1;
		}
	}

	for (int r = N; r > 0; r--) {
		for (int c = N; c >= 1; c--) {
			if (A[r][c] != A[r - 1][c + 1]) dp4[r][c] = 0;
			if (A[r][c] == A[r - 1][c + 1]) dp4[r][c] = min(dp4[r + 1][c], dp4[r][c + 1]) + 1;
		}
	}

	int ans = 0;
	for (int r = 2; r < N; r++) {
		for (int c = 2; c < N; c++) {
			int t = dp1[r - 1][c];
			chmin(t, dp2[r][c - 1]);
			chmin(t, dp3[r][c + 1]);
			chmin(t, dp4[r + 1][c]);
			chmin(t, min({ r - 1, c - 1, N - r, N - c }));
			chmax(ans, t);
		}
	}
	Cout(1+2*ans*(ans+1));
	return 0;
}
accuracy: 1
time_ms: 200
memory_kb: 207324
final_rank: 2

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n;
    cin >> n;
    vector<vector<char>> s(n + 2, vector<char>(n + 2, '.'));
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            cin >> s[i + 1][j + 1];
        }
    }
    vector<vector<int>> dp1(n + 2, vector<int>(n + 2, 0)), dp2(n + 2, vector<int>(n + 2, 0));
    vector<vector<int>> dp3(n + 2, vector<int>(n + 2, 0)), dp4(n + 2, vector<int>(n + 2, 0));
    for (int i = 1; i <= n; ++i) {
        for (int j = n; j >= 1; j--) {
            if (s[i][j] == s[i - 1][j - 1]) {
                dp1[i][j] = min(dp1[i - 1][j], dp1[i][j + 1]) + 1;
            }
        }
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (s[i][j] == s[i + 1][j - 1]) {
                dp2[i][j] = min(dp2[i - 1][j], dp2[i][j - 1]) + 1;
            }
        }
    }
    for (int i = n; i >= 1; --i) {
        for (int j = 1; j <= n; ++j) {
            if (s[i][j] == s[i + 1][j + 1]) {
                dp3[i][j] = min(dp3[i + 1][j], dp3[i][j - 1]) + 1;
            }
        }
    }
    for (int i = n; i >= 1; --i) {
        for (int j = n; j >= 1; --j) {
            if (s[i][j] == s[i - 1][j + 1]) {
                dp4[i][j] = min(dp4[i + 1][j], dp4[i][j + 1]) + 1;
            }
        }
    }

    ll res = 1;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            ll x = 1e9;
            x = min(x, (ll)dp1[i][j + 1] + 1);
            x = min(x, (ll)dp2[i - 1][j] + 1);
            x = min(x, (ll)dp3[i][j - 1] + 1);
            x = min(x, (ll)dp4[i + 1][j] + 1);
            res = max(res, 2LL * x * (x + 1) - 4 * x + 1);
        }
    }
    cout << res << endl;
}
accuracy: 1
time_ms: 290
memory_kb: 207400
final_rank: 4

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

using ll=long long;
using vll=vector<ll>;
using vvll=vector<vll>;
#define rep(i,s,t) for(ll i=s;i<t;i++)



int main(){
    ll N;
    cin>>N;
    vector<vector<char>> S(N,vector<char>(N));
    rep(i,0,N){
        string T;
        cin>>T;
        rep(j,0,N){
            S[i][j]=T[j];
        }
    }
    vvll DP(N+1,vll(N+1,1e18));
    rep(i,0,N)rep(j,0,N){
        DP[i][j]=min({i+1,j+1,N-i,N-j});
    }
    rep(t,0,4){
        vvll SP(N+1,vll(N+1,0));
        rep(i,0,N){
            rep(j,0,N){
                if(i==N-1||j==0){
                    SP[i+1][j+1]=0;
                }
                else if(S[i+1][j-1]!=S[i][j]){
                    SP[i+1][j+1]=0;
                }
                else{
                    SP[i+1][j+1]=min(SP[i][j+1],SP[i+1][j])+1;
                }
                DP[i][j]=min(DP[i][j],SP[i][j+1]);
            }
        }

        vvll NDP(N,vll(N));
        vector<vector<char>> NS(N,vector<char>(N));
        rep(i,0,N)rep(j,0,N){
            NDP[i][j]=DP[j][N-1-i];
            NS[i][j]=S[j][N-i-1];
        }
        swap(NDP,DP);
        swap(NS,S);

    }
    ll an=1;
    rep(i,0,N)rep(j,0,N){
        ll d=DP[i][j];
        an=max(an,2*d*d+2*d+1);
    }
    cout<<an<<endl;
}
accuracy: 1
time_ms: 980
memory_kb: 314904
final_rank: 5