HackerRank World Codesprint: Ema’s Supercomputer
Ema’s Supercomputer
問題
障害物の置かれた盤面が与えられる。これに十字の形のブロックの塊をふたつ置きたい。 置いたブロック同士が重なってはいけない。 置いたブロックふたつの面積の積の最大値を答えよ。
解説
$W, H \le 15$で計算量的にはまったく問題ないので、丁寧に実装する。
実装
#include <iostream>
#include <vector>
#define repeat(i,n) for (int i = 0; (i) < (n); ++(i))
typedef long long ll;
using namespace std;
const int dy[] = { -1, 1, 0, 0 };
const int dx[] = { 0, 0, 1, -1 };
int area(int l) { return 4*l+1; }
int value(int y, int x, int l1, int l2) {
if (y > x) swap(y, x);
int ans = 0;
if (y == 0) {
repeat (t,x) {
ans = max(ans, area(min(t,l1)) * area(min(x-t-1,l2)));
}
} else {
repeat (t,l1+1) {
int u =
t < y ? l2 :
t < x ? min(x-1, l2) :
min(y-1, l2);
ans = max(ans, area(t) * area(u));
}
}
return ans;
}
int main() {
int h, w; cin >> h >> w;
vector<vector<bool> > is_good(h, vector<bool>(w));
repeat (y,h) repeat (x,w) {
char c; cin >> c;
is_good[y][x] = c == 'G';
}
auto is_on_field = [=](int y, int x) { return 0 <= y and y < h and 0 <= x and x < w; };
vector<vector<int> > l(h, vector<int>(w)); // possible length of 4 bars
repeat (y,h) repeat (x,w) {
while (true) {
bool valid = true;
repeat (i,4) {
int ny = y + l[y][x] * dy[i];
int nx = x + l[y][x] * dx[i];
if (not is_on_field(ny, nx) or not is_good[ny][nx]) {
valid = false;
break;
}
}
if (not valid) break;
++ l[y][x];
}
}
int ans = 0;
repeat (y1,h) repeat (x1,w) if (l[y1][x1]) {
repeat (y2,h) repeat (x2,w) if (l[y2][x2]) {
if (y1 != y2 or x1 != x2) {
ans = max(ans, value(abs(y1-y2), abs(x1-x2), l[y1][x1]-1, l[y2][x2]-1));
}
}
}
cout << ans << endl;
return 0;
}