#include using namespace std; const char EMPTY = ' '; const char SUN = '*'; const char HOUSE = '^'; const char CHUPA = '!'; const char LEFT = '/'; const char RIGHT = '\\'; const char BIRD = 'v'; const char DRAKE = 'D'; const char GRILL = 'G'; #define int long long const int N = 55; int n; char grid[N][N]; inline bool inGrid(int x, int y) { return x >= 0 && y >= 0 && x < n && y < n; } inline void readData() { cin >> n; string s; getline(cin, s); for (int i = 0; i < n; i++) { getline(cin, s); for (int j = 0; j < n; j++) { grid[i][j] = s[j]; } } } int getHouseCount() { int ans = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == HOUSE) { ans++; } } } return ans; } int getSunCount() { int ans = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == SUN) { ans++; } } } return ans; } int getGrillCount() { int ans = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == GRILL) { ans++; } } } return ans; } int getDrakeCount() { int ans = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == DRAKE) { ans++; } } } return ans; } int getOnlyBirdCount() { int ans = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == BIRD) { ans++; } } } return ans; } int getChupaCount() { int ans = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == CHUPA) { ans++; } } } return ans; } int getEmptyCount() { int ans = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == EMPTY) { ans++; } } } return ans; } int getLeftCount() { int ans = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == LEFT) { ans++; } } } return ans; } int getRightCount() { int ans = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == RIGHT) { ans++; } } } return ans; } int getBirdCount() { return getDrakeCount() + getOnlyBirdCount(); } struct cell { int x, y; cell(int x, int y) : x(x), y(y) {}; }; vector getAdj(int x, int y) { assert(inGrid(x, y)); vector adj; for (int dx = -1; dx <= 1; dx += 2) { int nx = x + dx; int ny = y; if (inGrid(nx, ny)) { adj.emplace_back(nx, ny); } } for (int dy = -1; dy <= 1; dy += 2) { int nx = x; int ny = y + dy; if (inGrid(nx, ny)) { adj.emplace_back(nx, ny); } } return adj; } int getSuns() { int dx[8] = {-1, -1, -1, 0, 1, 1, 1, 0}; int dy[8] = {-1, 0, 1, 1, 1, 0, -1, -1}; int sum = 0; for (int i = 0; i < n; ++i){ for (int j = 0; j < n; ++j){ if (grid[i][j] == EMPTY || grid[i][j] == SUN)continue; bool good = false; for (int d = 0; d < 8; ++d){ int x = i; int y = j; x += dx[d]; y += dy[d]; while (inGrid(x, y)){ if (grid[x][y] == EMPTY){ x += dx[d]; y += dy[d]; continue; } if (grid[x][y] == SUN)good = true; break; } } if (good)sum += 100; } } return sum; } struct nazik { bool us[N][N]; int mx; void clea(){ mx = 0; memset(us, 0, sizeof(us)); } }; nazik us; int getBirdWidth(int x, int y) { int s = 1; int l = x; int r = y; r--; while (inGrid(l, r) && (grid[l][r] == BIRD || grid[l][r] == DRAKE)) { s++; r--; } l = x; r = y; r++; while (inGrid(l, r) && (grid[l][r] == BIRD || grid[l][r] == DRAKE)) { s++; r++; } return s; } void dfs_1(int x, int y){ us.us[x][y] = true; us.mx = max(us.mx, getBirdWidth(x, y)); for (cell c : getAdj(x, y)){ int l = c.x; int r = c.y; if (!us.us[l][r] && (grid[l][r] == BIRD || grid[l][r] == DRAKE))dfs_1(l, r); } } int getBiggestBird() { int sum = 0; us.clea(); for (int i = 0; i < n; ++i){ for (int j = 0; j < n; ++j){ if (grid[i][j] != BIRD && grid[i][j] != DRAKE)continue; if (us.us[i][j])continue; us.mx = 0; dfs_1(i, j); sum += us.mx * 500; } } return sum; } void dfs_2(int x, int y){ us.us[x][y] = true; for (cell c : getAdj(x, y)) { int l = c.x; int r = c.y; if (!us.us[l][r] && (grid[l][r] == BIRD || grid[l][r] == DRAKE))dfs_2(l, r); if (!us.us[l][r])us.mx++; } us.mx += 4 - (int)getAdj(x, y).size(); } int getPerimeter() { int sum = 0; us.clea(); for (int i = 0; i < n; ++i){ for (int j = 0; j < n; ++j){ if (grid[i][j] != BIRD && grid[i][j] != DRAKE)continue; if (us.us[i][j])continue; us.mx = 0; dfs_2(i, j); sum += us.mx * 60; } } return sum; } int getHouseViewUp() { int sum = 0; for (int i = 0; i < n; ++i){ for (int j = 0; j < n; ++j){ if (grid[i][j] != HOUSE)continue; int x = i; int y = j; y--; while (inGrid(x, y) && grid[x][y] == EMPTY){ sum += 10; y--; } } } return sum; } int getBlocks3By3() { set < string > q; for (int i = 0; i + 2 < n; ++i){ for (int j = 0; j + 2 < n; ++j){ string s = "" + grid[i][j]; s = s + grid[i][j + 1]; s = s + grid[i][j + 2]; s = s + grid[i + 1][j]; s = s + grid[i + 1][j + 1]; s = s + grid[i + 1][j + 2]; s = s + grid[i + 2][j]; s = s + grid[i + 2][j + 1]; s = s + grid[i + 2][j + 2]; q.insert(s); } } return (int)q.size(); } int getAnimals1() { int sum = 0; for (int i = 0; i < n; ++i){ for (int j = 0; j < n; ++j){ if (grid[i][j] != DRAKE && grid[i][j] != BIRD && grid[i][j] != CHUPA)continue; for (cell c : getAdj(i, j)) { if (grid[c.x][c.y] == EMPTY)sum += 15; } } } return sum; } void dfs_3(int x, int y){ if (us.us[x][y])return; us.us[x][y] = true; if (grid[x][y] == EMPTY) { for (cell c : getAdj(x, y)){ int l = c.x; int r = c.y; if (!us.us[l][r])dfs_3(l, r); } } else { } } int getFreedom() { us.clea(); for (int i = 0; i < n; ++i){ dfs_3(i, 0); dfs_3(i, n - 1); dfs_3(0, i); dfs_3(n - 1, i); } int sum = 0; for (int i = 0; i < n; ++i){ for (int j = 0; j < n; ++j){ if (us.us[i][j] && grid[i][j] != EMPTY)sum += 7; } } return sum; } int getChupacabra() { int dx[8] = {2, 2, 1, 1, -2, -2, -1, -1}; int dy[8] = {1, -1, 2, -2, 1, -1, 2, -2}; int sum = 0; for (int i = 0; i < n; ++i){ for (int j = 0; j < n; ++j){ if (grid[i][j] != DRAKE && grid[i][j] != BIRD)continue; bool good = false; for (int d = 0; d < 8; ++d){ int x = i + dx[d]; int y = j + dy[d]; if (inGrid(x, y) && grid[x][y] == CHUPA) { good = true; break; } } if (good)sum += 200; } } return sum; } int getPeaks() { int sum = 0; vector < cell > peaks; for (int i = 0; i < n; ++i){ for (int j = 0; j + 1 < n; ++j){ if (grid[i][j] == LEFT && grid[i][j + 1] == RIGHT)peaks.push_back({i, j}); } } int sz = (int)peaks.size(); for (int i = 0; i < sz; ++i) { int mx = 0; for (int j = 0; j < sz; ++j){ if (i == j)continue; mx = max(mx, abs(peaks[i].x - peaks[j].x) + abs(peaks[i].y - peaks[j].y)); } sum += 50 * mx; } return sum; } int getDrakeGrill() { int ans = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] != DRAKE) { continue; } vector adj = getAdj(i, j); for (cell& c : adj) { if (grid[c.x][c.y] == GRILL) { ans += 500; break; } } } } return ans; } int getMinFrequency() { if (getEmptyCount() == n * n) { return 0; } int min_freq = INT_MAX; if (getSunCount()) { min_freq = min(min_freq, getSunCount()); } if (getHouseCount()) { min_freq = min(min_freq, getHouseCount()); } if (getChupaCount()) { min_freq = min(min_freq, getChupaCount()); } if (getLeftCount()) { min_freq = min(min_freq, getLeftCount()); } if (getRightCount()) { min_freq = min(min_freq, getRightCount()); } if (getOnlyBirdCount()) { min_freq = min(min_freq, getOnlyBirdCount()); } if (getDrakeCount()) { min_freq = min(min_freq, getDrakeCount()); } if (getGrillCount()) { min_freq = min(min_freq, getGrillCount()); } int col = 0; if (getSunCount() == min_freq) { col++; } if (getHouseCount() == min_freq) { col++; } if (getChupaCount() == min_freq) { col++; } if (getLeftCount() == min_freq) { col++; } if (getRightCount() == min_freq) { col++; } if (getOnlyBirdCount() == min_freq) { col++; } if (getDrakeCount() == min_freq) { col++; } if (getGrillCount() == min_freq) { col++; } return 10 * min_freq * col; } int getEmpty() { return getEmptyCount(); } int getAnimals2() { int drakes = getDrakeCount(); int birds = getOnlyBirdCount(); int chupas = getChupaCount(); return drakes * birds * chupas; } int getHouseViewDown() { int ans = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] != HOUSE) { continue; } int x = i - 1; int y = j; while(inGrid(x, y) && grid[x][y] == EMPTY) { ans += 5; x--; } } } return ans; } int getGrillDrake() { int ans = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] != GRILL) { continue; } vector adj = getAdj(i, j); for (cell& c : adj) { if (grid[c.x][c.y] == DRAKE) { ans += 50; break; } } } } return ans; } int getHouseGrill() { return 3 * min(getHouseCount(), getGrillCount()); } int getMoney() { int ans = 0; ans += getSuns(); ans += getBiggestBird(); ans += getPerimeter(); ans += getHouseViewUp(); ans += getBlocks3By3(); ans += getAnimals1(); ans += getFreedom(); ans += getChupacabra(); ans += getPeaks(); ans += getDrakeGrill(); ans += getMinFrequency(); ans += getEmpty(); ans += getAnimals2(); ans += getHouseViewDown(); ans += getGrillDrake(); ans += getHouseGrill(); return ans; } main() { readData(); cout << getMoney(); return 0; }