#include #include #include #include #include #include #include using namespace std; //"Infinity" distance, meaning there's no walking path to an exit. #define INF 1000000 int rows, cols; vector grid; //The minimum walking (no teleporting) distance of each space from any exit int walkDist[200][200]; /* Checks if a space should be added to the queue (in the BFS used to find walking distances). If so, adds the space and sets its walking distance to the thisDistance parameter.*/ void processSpace(int row, int col, int thisDistance, queue >& toProcess) { //Don't add if the space is outside the grid if (row < 0 || row >= rows || col < 0 || col >= cols) return; //Don't add if the space is a wall if (grid[row][col] == 'X') return; //Don't add if the space has already been added to the queue if (walkDist[row][col] < INF) return; toProcess.push(make_pair(row, col)); walkDist[row][col] = thisDistance; } int main() { ifstream infile("teleport.in"); ofstream outfile("teleport.out"); while(true) { //Reset data structures grid.clear(); for (int i = 0; i < 200; i++) for (int j = 0; j < 200; j++) walkDist[i][j] = INF; //Input number of rows and columns infile >> rows >> cols; if (rows == 0) { return 0; } //Input the grid for (int i = 0; i < rows; i++) { string str; infile >> str; grid.push_back(str); } //Total number of non-wall spaces int totalSpaces = 0; //Starting row and column int startRow = 0, startCol = 0; //BFS queue to be used for calculating walking distances for each space queue > toProcess; for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) { //If the space is not a wall, add to total number of non-wall spaces. if (grid[i][j] != 'X') totalSpaces++; //If the space is the starting location, set the starting row and column. if (grid[i][j] == 'Y') { startRow = i; startCol = j; } //If the space is an exit, put it on the queue for BFS with distance 0. if (grid[i][j] == 'E') { walkDist[i][j] = 0; toProcess.push(make_pair(i, j)); } } //Do BFS to find the walking distance for each space. while (!toProcess.empty()) { pair space = toProcess.front(); toProcess.pop(); int r = space.first; int c = space.second; int newDist = walkDist[r][c] + 1; processSpace(r+1, c, newDist, toProcess); processSpace(r, c+1, newDist, toProcess); processSpace(r-1, c, newDist, toProcess); processSpace(r, c-1, newDist, toProcess); } //Number of spaces with walking distance equal to the index vector numSpaces(totalSpaces+1); //Number of spaces with walking distance <= the index vector cumNumSpaces(totalSpaces+1); //Average walking distance for all spaces with walking distance <= the index vector averageDist(totalSpaces+1); //Calculate numSpaces for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) { if (walkDist[i][j] < INF) numSpaces[walkDist[i][j]]++; } //Calculate cumNumSpaces and averageDist cumNumSpaces[0] = numSpaces[0]; averageDist[0] = 0; for (int i = 1; i < totalSpaces; i++) { cumNumSpaces[i] = numSpaces[i] + cumNumSpaces[i-1]; averageDist[i] = i * numSpaces[i] + averageDist[i-1]; } // Finish calculating the average distance by dividing by the number of spaces for (int i = 0; i < totalSpaces; i++) averageDist[i] = averageDist[i] / cumNumSpaces[i]; /* We need to choose a minimum distance from which we should walk instead of teleporting. Find the choice which will minimize the expected distance (walking + teleporting) from the starting space.*/ double minExpVal = INF; int bestChoice = 0; /*Try each distance from 0 to the total number of non-wall spaces. In this loop, assume we start by teleporting.*/ for (int dist = 0; dist < totalSpaces; dist++) { //Expected number of teleports to get within our chosen distance double expVal = 1.0 * totalSpaces / cumNumSpaces[dist]; //Expected number of spaces to walk once we're within that distance expVal += 1.0 * averageDist[dist]; if (expVal < minExpVal) { minExpVal = expVal; bestChoice = dist; } } double answer; //If the space is closer than the minimum distance we chose, just walk. if (walkDist[startRow][startCol] <= bestChoice) answer = walkDist[startRow][startCol]; //Otherwise, teleport. else answer = minExpVal; outfile << fixed << setprecision(3) << answer << endl; } return 0; }