USACO 2019 January Contest Silver Division - Icy Perimeter#
Problem link: here
Solution Author: Stefan Dascalescu
Problem Solution#
We will use floodfill to compute a temporary area and perimeter for the given component and then we compare them with the best such areas/perimeters we found so far. One has to pay attention to the way we compute the area and the perimeter as for a given square, in order to increase the perimeter, we have to add up 1 for each side that is adjacent to a square not in the component.
Source code#
The source code in C++ can be seen below.
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e3 + 5;
char mat[MAXN][MAXN];
bool visited[MAXN][MAXN];
int dx[4] = {-1, 0, 1, 0}; // Directions
int dy[4] = {0, 1, 0, -1};
long long perim = 0, ar = 0, perimeter = 0, area = 0;
// floodfill (Lee Algorithm)
void lee(int a, int b, int n) {
queue<pair<int, int>> q;
q.push({a, b});
visited[a][b] = 1;
while (!q.empty()) {
int val1 = q.front().first, val2 = q.front().second;
q.pop();
for (int dir = 0; dir < 4; dir++) {
int newX = val1 + dx[dir]; // New coords
int newY = val2 + dy[dir];
if (newX < 0 || newX >= n || newY < 0 || newY >= n) { // If it's not in the matrix
perim++;
continue;
}
if (visited[newX][newY]) { // If it was already visited
continue;
}
if (mat[newX][newY] == '.') { // If it's a '.' (empty space) update the temporary perimeter
perim++;
continue;
}
if (mat[newX][newY] == '#') { // If it's a cell of ice cream, update area.
ar++;
}
visited[newX][newY] = 1; // Mark as visited
q.push({newX, newY}); // Push new values
}
}
}
int main() {
freopen("perimeter.in", "r", stdin);
freopen("perimeter.out", "w", stdout);
int n, lin, col;
cin >> n;
for (lin = 0; lin < n; lin++) {
for (col = 0; col < n; col++) {
cin >> mat[lin][col];
}
}
for (lin = 0; lin < n; lin++) {
for (col = 0; col < n; col++) {
if (!visited[lin][col] &&
mat[lin][col] == '#') { // If we haven't visited it yet and it's an ice cream cell
lee(lin, col, n); // Calculate using Lee Algorithm the new area and perimeter
++ar;
if (area == ar) { // if our current area and the new one are equal
perimeter = min(perimeter, perim); // just consider the smaller perimeter
} else if (ar > area) { // if our new area is bigger
perimeter = perim; // update both values to the newly calculated ones
area = ar;
}
perim = ar = 0; // reset new area and perimeter to 0
}
}
}
cout << area << " " << perimeter; // output the values
return 0;
}