用BFS处理每个点之间的距离,二分答案,用状态DP判断是否能够可以。
dp[i][j]表示当前位于i点已经遍历集合j时的最大能量值。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <queue>
using namespace std;
typedef long long LL;
const int maxn=16;
const int inf=0x7f7f7f7f;
char grid[maxn][maxn];
int f[maxn][(1<<maxn)+10];
bool pool[maxn];
int num[maxn][maxn];
int g[maxn][maxn];
bool bvis[maxn][maxn];
int n,m;
int N,state;
const int mv[4][2]= {0,1,0,-1,1,0,-1,0};
struct Point
{
int x,y,s;
Point(int xx,int yy,int ss):x(xx),y(yy),s(ss) {}
};
void bfs(int x,int y)
{
memset(bvis,0,sizeof(bvis));
queue<Point> que;
que.push(Point(x,y,0));
bvis[x][y]=true;
int now=num[x][y];
g[now][now]=0;
while(!que.empty())
{
Point p=que.front();
que.pop();
for(int i=0; i<4; ++i)
{
int nx=p.x+mv[i][0],ny=p.y+mv[i][1],ns=p.s+1;
if(0<=nx&&nx<n&&0<=ny&&ny<m)
{
if(grid[nx][ny]=='D'||bvis[nx][ny])
continue;
bvis[nx][ny]=true;
if(grid[nx][ny]=='F'||grid[nx][ny]=='G'||grid[nx][ny]=='Y')
{
g[now][num[nx][ny]]=ns;
}
que.push(Point(nx,ny,ns));
}
}
}
}
bool prepare()
{
memset(g,0x7f,sizeof(g));
for(int i=0; i<n; ++i)
{
for(int j=0; j<m; ++j)
{
if(grid[i][j]=='F'||grid[i][j]=='G'||grid[i][j]=='Y')
bfs(i,j);
}
}
for(int i=0; i<N; ++i)
for(int j=i+1; j<N; ++j)
{
if((state&(1<<i))&&(state&(1<<j)))
{
if(g[i][j]==inf)
return false;
}
}
return true;
}
int getUpper(int sx,int sy)
{
int res=0;
int last=0;
for(int i=1; i<N; ++i)
{
if(state&(1<<i))
{
res+=g[last][i];
last=i;
}
}
return res;
}
bool dp(const int full)
{
memset(f,-1,sizeof(f));
f[0][1]=full;
for(int i=1; i<(1<<N); ++i)
{
for(int j=0; j<N; ++j)
{
if(!(i&(1<<j)))
{
for(int k=0; k<N; ++k)
{
if(i&(1<<k))
{
int s=i|(1<<j);
if(f[k][i]>=g[j][k])
{
if(pool[j])
f[j][s]=full;
else
f[j][s]=max(f[j][s],f[k][i]-g[j][k]);
}
}
}
}
}
}
for(int i=1; i<(1<<N); ++i)
{
for(int j=0; j<N; ++j)
{
if(f[j][i]>=0&&(i&state)==state)
{
return true;
}
}
}
return false;
}
int binSearch(int low,int high)
{
int mid=low+(high-low)/2;
while(low<high)
{
if(dp(mid))
high=mid;
else
low=mid+1;
mid=low+(high-low)/2;
}
return high;
}
int main()
{
while(scanf("%d%d",&n,&m))
{
if(!n&&!m)
break;
memset(num,0,sizeof(num));
memset(pool,0,sizeof(pool));
state=0;
N=0;
int sx,sy;
for(int i=0; i<n; ++i)
{
scanf("%s",grid[i]);
for(int j=0; grid[i][j]; ++j)
{
if(grid[i][j]=='G'||grid[i][j]=='Y')
{
N++;
if(grid[i][j]=='Y')
state|=(1<<N);
else
pool[N]=true;
num[i][j]=N;
}
else if(grid[i][j]=='F')
{
num[i][j]=0;
state+=1;
sx=i;
sy=j;
}
}
}
++N;
if(!prepare())
puts("-1");
else
{
int up=getUpper(sx,sy);
int ans=binSearch(0,up);
printf("%d\n",ans);
}
}
return 0;
}