/*
To a n*m figure, F for the starting point, G for the charge pool, a charge pool can only be used once, but can use multiple charging cells, only the battery charge to the maximum (raw power), can walk through no, D can not go,
The question is, what's the original amount of power to go through all Y's?
dp+ state compression + dichotomy +BFS
DP[I][J] Indicates the state is the maximum amount of power that reaches J in the I State
*/
#include <stdio.h> #include <string.h> #include <queue> #define MAX (A, B) a>b?a:b#define Min (A, B) a >b?b:ausing namespace Std;char map[20][20];int map1[20][20],bu[4][2]= {0,1,0,-1,1,0,-1,0},dis[20][20],ac,fis,n,m , Dp[1<<16][16],len;//ac records the state of the beginning and all Y, and FIS records the starting point struct node{int x,y,step;} Node[20];int BFS (int a,int b) {memset (map1,0,sizeof (MAP1)); Node l,r,s; Queue<node> v; S=node[a]; S.step=0; Map1[s.x][s.y]=1; V.push (s); while (!v.empty ()) {L=v.front (); V.pop (); if (L.X==NODE[B].X&&L.Y==NODE[B].Y) return l.step; for (int i=0;i<4;i++) {int aa=l.x+bu[i][0]; int bb=l.y+bu[i][1]; if (aa>=0&&aa<n&&bb>=0&&bb<m&&map[aa][bb]!= ' D ' &&MAP1[AA][BB ]==0) {map1[aa][bb]=1; R.X=AA; R.Y=BB; r.step=l.step+1; V.push (R); }}} return-1;} void Inint () {memset (dis,-1,sizeof (dis)); for (int i=0, i<len; i++) for (int j=i; j<len; J + +) if (i==j) {dis[i][j]=0 ; dis[j][i]=0; } else {Dis[i][j]=bfs (i,j); DIS[J][I]=DIS[I][J]; }}int check (int Min) {memset (dp,-1,sizeof (DP)); dp[1<<fis][fis]=min; for (int i=0;i< (1<<len); i++)//enumerates all state {for (int j=0;j<len;j++) {if (i& (1<&L t;j)) ==0| | Dp[i][j]==-1) continue;//to determine whether in the I state is J, if not through J, the latter State can not expand on continue if ((I&AC) ==ac&&dp[i][j]!=-1)//Determine whether Reach the final state return 1; for (int k=0;k<len;k++) {if (i& (1<<k))) continue;//exclude I state has passed K if (dis [j] [k]<0) continue;//j can reach K int tep=dp[i][j]-dis[j][k];//the charge if (tep<0) continue after reaching K; Dp[i| (1<<k)] [K]=max (Dp[i| ( 1<<k)][k],tep); if (map[node[k].x][node[k].y]== ' G ') dp[i| ( 1<<k)][k]=min; }}} return 0;} int main () {while (scanf ("%d%d", &n,&m)!=eof&& (n+m)!=0) {len=0; ac=0; for (int i=0; i<n; i++) {scanf ("%s", Map[i]); for (int j=0; j<m; J + +) {if (map[i][j]== ' G ') {node[len].x=i ; Node[len++].y=j; } else if (map[i][j]== ' F ') {Fis=len; ac=ac| (1<<len); Node[len].x=i; Node[len++].y=j; } else if (map[i][j]== ' Y ') {ac=ac| ( 1<<len); Node[len].x=i; Node[len++].y=j; }}} inint (); int L=1,r=225; int ans=400; while (l<r) {int mid= (L+R)/2; if (check (mid)) {ans=min (ans,mid); R=mid; } else l=mid+1; } if (ans==400) printf (" -1\n"); else printf ("%d\n", ans); } return 0;}
HDU 3681 Prison Break