Sicily 1892. Gold

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;
}                                 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值