1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 #include <queue> 6 using namespace std; 7 typedef long long LL; 8 9 const int MAXN = 1 << 16; 10 const int MAXV = 20; 11 12 int fx[] = {-1, 0, 1, 0}; 13 int fy[] = {0, 1, 0, -1}; 14 15 char mat[MAXV][MAXV]; 16 int id[MAXV][MAXV], dis[MAXV][MAXV], Gcnt, Ycnt; 17 int n, m; 18 19 bool isOn(int state, int i) { 20 return (state >> i) & 1; 21 } 22 23 int moveState(int state, int i) { 24 return state ^ (1 << i); 25 } 26 27 bool atEnd(int state) { 28 return state % (1 << Ycnt) == 0; 29 } 30 31 bool isGYF(char c) { 32 return c == 'G' || c == 'Y' || c == 'F'; 33 } 34 35 int vis[MAXV][MAXV]; 36 37 void bfsdis(int x, int y) { 38 memset(vis, 0x7f, sizeof(vis)); 39 vis[x][y] = 0; 40 queue<pair<int, int> > que; 41 que.push(make_pair(x, y)); 42 int st = id[x][y]; 43 while(!que.empty()) { 44 int x = que.front().first, y = que.front().second; que.pop(); 45 if(isGYF(mat[x][y])) dis[st][id[x][y]] = vis[x][y]; 46 for(int i = 0; i < 4; ++i) { 47 int tx = x + fx[i], ty = y + fy[i]; 48 if(mat[tx][ty] != 'D' && vis[x][y] + 1 < vis[tx][ty]) { 49 vis[tx][ty] = vis[x][y] + 1; 50 que.push(make_pair(tx, ty)); 51 } 52 } 53 } 54 } 55 56 void init() { 57 Ycnt = 0; 58 for(int i = 1; i <= n; ++i) { 59 for(int j = 1; j <= m; ++j) { 60 if(mat[i][j] != 'Y') continue; 61 id[i][j] = Ycnt++; 62 } 63 } 64 Gcnt = Ycnt; 65 for(int i = 1; i <= n; ++i) { 66 for(int j = 1; j <= m; ++j) { 67 if(mat[i][j] != 'G') continue; 68 id[i][j] = Gcnt++; 69 } 70 } 71 for(int i = 1; i <= n; ++i) { 72 for(int j = 1; j <= m; ++j) { 73 if(mat[i][j] != 'F') continue; 74 id[i][j] = Gcnt; 75 } 76 } 77 memset(dis, 0x7f, sizeof(dis)); 78 for(int i = 1; i <= n; ++i) { 79 for(int j = 1; j <= m; ++j) { 80 if(!isGYF(mat[i][j])) continue; 81 bfsdis(i, j); 82 } 83 } 84 } 85 86 int best[MAXN][MAXV]; 87 bool inque[MAXN][MAXV]; 88 89 bool check(int energy) { 90 memset(inque, 0, sizeof(inque)); 91 memset(best, 0, sizeof(best)); 92 best[(1 << Gcnt) - 1][Gcnt] = energy; 93 queue<pair<int, int> > que; 94 que.push(make_pair((1 << Gcnt) - 1, Gcnt)); 95 while(!que.empty()) { 96 int state = que.front().first, pos = que.front().second; que.pop(); 97 inque[state][pos] = false; 98 for(int i = 0; i < Gcnt; ++i) { 99 if(!isOn(state, i)) continue; 100 int newState = moveState(state, i); 101 if(i >= Ycnt) { 102 if(best[state][pos] >= dis[pos][i] && best[newState][i] == 0) { 103 best[newState][i] = energy; 104 inque[newState][i] = true; 105 que.push(make_pair(newState, i)); 106 } 107 } else { 108 if(best[state][pos] - dis[pos][i] >= 0 && atEnd(newState)) return true; 109 if(best[state][pos] - dis[pos][i] > best[newState][i]) { 110 best[newState][i] = best[state][pos] - dis[pos][i]; 111 if(!inque[newState][i]) { 112 inque[newState][i] = true; 113 que.push(make_pair(newState, i)); 114 } 115 } 116 } 117 } 118 } 119 return false; 120 } 121 122 int solve() { 123 if(Ycnt == 0) return 0; 124 int st = Gcnt; 125 for(int i = 0; i < Ycnt; ++i) 126 if(dis[i][st] > 2014) return -1; 127 int l = 1, r = dis[st][0]; 128 for(int i = 0; i < Ycnt - 1; ++i) r += dis[i][i + 1]; 129 while(l < r) { 130 int mid = (l + r) >> 1; 131 if(!check(mid)) l = mid + 1; 132 else r = mid; 133 } 134 return l; 135 } 136 137 int main() { 138 while(scanf("%d%d", &n, &m) != EOF) { 139 if(n == 0 && m == 0) break; 140 memset(mat, 'D', sizeof(mat)); 141 for(int i = 1; i <= n; ++i) scanf("%s", &mat[i][1]); 142 init(); 143 printf("%d\n", solve()); 144 } 145 }