1892. Gold
Constraints
Time Limit: 4 secs, Memory Limit: 61.296875 MB
Description
One rogue entered into the dead well to dig the gold. The rogue is so powerful that he has ability calling “slink” for entering the well quietly and the masters couldn’t discover him. But the slink ability spent him much energy and if the energy was too low, he was immediately caught by the masters and died. So he must arrange the digging plan.
Dead well can be described as an n*n rectangle. For masters were so many that you can assume that everywhere were masters except the golden point (which had gold and the rogue wants to go most), the entrance and the exit. And then dead well was also a maze. The rogue can only walk into the master point, golden point, entrance and exit. He can walk four directions of north, south, east and west. When the rogue entered into the golden points, the entrance point, or the exit point, he can recover his energy in no time because there weren’t any masters. Rogue must go out of the dead well at the exit point.
You job is that to calculate how many golden points he can visit and how many master points he at least visited.
Input
This problem has multiple cases. In each case, the first line is two integers n(1<=n<=100) and m (1<=m<=200), which is the size of the dead well and the maximum master points he can slink at most. Then there are n lines of string without space. In each string, there are n characters. “E” stands for the entrance, “X” stands for the exit, “G” stands for the golden point, “-” stands for the master point, and “#”stands for the wall. You can assume that there are at most 16 golden points.
The input is terminated by n=0.
Output
In each test case, you must print two integers in one line. The first integer is the golden point he can dig at most and the second integer is the least master points he must visit when he digs the most gold mines. If it’s impossible to go out of the dead well, print a string of “Impossible”.
Sample Input
3 1 E-G #G- --X 0 0
Sample Output
2 3
// Problem#: 1892
// Submission#: 3592099
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <stdio.h>
#include <string.h>
#include <map>
#include <algorithm>
using namespace std;
const int MAXN = 100;
const int MAXG = 16;
const int INF = 1000000000;
int mov[4][2] = {-1, 0, 0, 1, 1, 0, 0, -1};
int n, m;
char G[MAXN][MAXN + 1];
bool mk[MAXN][MAXN];
map<pair<int, int>, int> Map;
int N;
int g[MAXG + 2][MAXG + 2];
int memo[MAXG + 2][1 << MAXG];
struct Node {
int r, c, d;
Node(int r_ = 0, int c_ = 0, int d_ = 0) {
r = r_;
c = c_;
d = d_;
}
};
Node open[MAXN * MAXN];
bool input() {
scanf("%d%d", &n, &m);
if (n == 0) return false;
for (int i = 0; i < n; i++) scanf("%s", G[i]);
return true;
}
void bfs(int r, int c) {
int u = Map[make_pair(r, c)];
memset(mk, 0, sizeof(mk));
open[0] = Node(r, c, 0);
mk[r][c] = true;
int head = 0, tail = 1;
while (head < tail) {
Node cur = open[head++];
for (int i = 0; i < 4; i++) {
int rr = cur.r + mov[i][0];
int cc = cur.c + mov[i][1];
if (rr >= 0 && rr < n && cc >= 0 && cc < n && !mk[rr][cc]) {
mk[rr][cc] = true;
if (G[rr][cc] == 'G' || G[rr][cc] == 'E' || G[rr][cc] == 'X') {
int v = Map[make_pair(rr, cc)];
g[u][v] = cur.d;
} else if (G[rr][cc] == '-' && cur.d + 1 <= m) {
open[tail++] = Node(rr, cc, cur.d + 1);
}
}
}
}
}
void construct() {
Map.clear();
N = 0;
int ei, ej;
int xi, xj;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (G[i][j] == 'G') {
Map[make_pair(i, j)] = N++;
} else if (G[i][j] == 'E') {
ei = i;
ej = j;
} else if (G[i][j] == 'X') {
xi = i;
xj = j;
}
}
}
Map[make_pair(ei, ej)] = N++;
Map[make_pair(xi, xj)] = N++;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
g[i][j] = INF;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (G[i][j] == 'G' || G[i][j] == 'E' || G[i][j] == 'X') {
bfs(i ,j);
}
}
}
for (int k = 0; k < N; k++) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
}
}
}
}
int f(int ed, int mask) {
if (memo[ed][mask] != -1) return memo[ed][mask];
memo[ed][mask] = INF;
for (int i = 0; i < N - 2; i++) {
if ((mask & (1 << i)) > 0 && i != ed) {
int t = f(i, mask & ~(1 << ed)) + g[i][ed];
memo[ed][mask] = min(memo[ed][mask], t);
}
}
return memo[ed][mask];
}
void _solve() {
if (g[N - 2][N - 1] == INF) {
puts("Impossible");
return;
}
int cnt = 0;
int mask = 0;
for (int i = 0; i < N - 2; i++) {
if (g[N - 2][i] < INF) {
cnt++;
mask |= (1 << i);
}
}
if (cnt == 0) {
printf("0 %d\n", g[N -2 ][N - 1]);
return;
}
memset(memo, -1, sizeof(memo));
for (int i = 0; i < N - 2; i++) {
memo[i][1 << i] = g[N - 2][i];
memo[N - 1][1 << i] = g[N - 2][i] + g[i][N - 1];
}
int min_cost = f(N - 1, mask);
printf("%d %d\n", cnt, min_cost);
}
void solve() {
construct();
_solve();
}
int main() {
while (input()) solve();
return 0;
}