<p>吐槽一下,最近事情真是多。。。大创+大挑+考试+实验报告(一个礼拜5个实验。。。)+各种抄作业+帮四省赛装电脑,然后一直没怎么做题。。。</p><p>然后再吐槽一下这道题,读题不细心真是惨啊。。。一开始看成了G点和Y点分别不超过15个,想想,加起来用30个点,我去。。。这怎么搞。。。拼命搞了两天没搞出来。。。两天以后又看了一下题目,发现是一共加起来不超过15个点(醉了,难怪我英语可能要挂科了),这就是一个普通的TSP问题了,不过并不是遍历所有的点一次,而是选定的点各一次,这个时候加一个末状态就好了。先建图,每个点做一次bfs就好了(找出最短路径),dp[s][i]表示第s状态最后到达i点的最大剩余体力。转移方程就是dp[s][j] = max(dp[pre_s][i]-dis[i][j]),这里要注意一下边界问题。。。对于TSP问题,我总觉的我的写法比较奇葩(但是都过了,以后如果出问题了再改吧)。最近感觉c++迭代器里面的东西确实好用。。。</p><p>下面直接给代码</p>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#define ll long long
#define FOR(i,x,y) for(int i = x;i < y;i ++)
#define IFOR(i,x,y) for(int i = x;i > y;i --)
using namespace std;
typedef pair<int,int> pii;
pii no[16];
int en,st,dis[16][16][16][16],n,N,M,dp[1<<16][16];
char mat[17][17];
int dx[4] = {-1,1,0,0},dy[4] = {0,0,-1,1};
void input(){
n = 0;
en = 0;
FOR(i,0,N){
scanf("%s",mat[i]);
FOR(j,0,M){
if(mat[i][j] == 'F'){
st = n;
en = en | (1<<n);
no[n++] = make_pair(i,j);
continue;
}
if(mat[i][j] == 'G'){
no[n++] = make_pair(i,j);
continue;
}
if(mat[i][j] == 'Y'){
en = en | (1<<n);
no[n++] = make_pair(i,j);
continue;
}
}
}
}
void bfs(pii um){
queue <pii> q;
dis[um.first][um.second][um.first][um.second] = 0;
q.push(um);
while(!q.empty()){
pii u = q.front(); q.pop();
int x = u.first,y = u.second;
FOR(i,0,4){
int nx = x + dx[i],ny = y + dy[i];
if(nx < 0 || nx >= N || ny < 0 || ny >= M) continue;
if(mat[nx][ny] == 'D') continue;
if(dis[um.first][um.second][nx][ny] != -1) continue;
dis[um.first][um.second][nx][ny] = dis[um.first][um.second][x][y] + 1;
q.push(make_pair(nx,ny));
}
}
}
bool init(){
memset(dis,-1,sizeof(dis));
FOR(i,0,n){
bfs(no[i]);
}
FOR(i,0,n){
if(mat[no[i].first][no[i].second] != 'G' && dis[no[st].first][no[st].second][no[i].first][no[i].second] == -1)
return false;
}
return true;
}
bool check(int p){
FOR(s,0,1<<n){
FOR(i,0,n)
dp[s][i] = -1;
}
dp[1<<st][st] = p;
FOR(s,0,1<<n){
if((s & (1<<st)) == 0) continue;
FOR(j,0,n){
if((s & (1<<j)) == 0) continue;
if(j == st) continue;
int pre_s = s ^ (1<<j);
FOR(i,0,n){
if((pre_s & (1<<i)) == 0) continue;
int tem = dis[no[i].first][no[i].second][no[j].first][no[j].second];
if(tem == -1) continue;
dp[s][j] = max(dp[pre_s][i]-tem,dp[s][j]);
}
if(dp[s][j] == -1) continue;
if((s & en) == en && dp[s][j] != -1) return true;
if(mat[no[j].first][no[j].second] == 'G') dp[s][j] = p;
}
}
return false;
}
int solve(){
int l = 0,r = 1111111;
check(2);
while(l < r){
int mid = (l+r)>>1;
if(!check(mid)) l = mid+1;
else r = mid;
}
return l;
}
int main(){
//freopen("test.in","r",stdin);
while(scanf("%d%d",&N,&M),(N || M)){
input();
if(en == (1<<st)) printf("0
");
else if(!init()) printf("-1
");
else printf("%d
",solve());
}
return 0;
}