Click to open link
Test instructions: In a map, D is not allowed to walk, F for the starting point, s for the open space, y is to collect things, and then G is a gas station, each step to consume a little energy, to the gas station can be filled with oil, but a gas station only once, asked from the starting point will all Y collect the minimum tank capacity required
Idea: This problem we can first regardless of the fuel tank directly to see how many steps you need to collect all Y, if not directly-1, and then two minutes of the smallest tank capacity, the inside of the gas station and Y are using state compression to judge the line, the only attention is to a state of the point, not access is no longer access, But to determine which of the energy remaining more, and then pressed into the queue on the line, not the normal solution, but good understanding is better to think more
#include <queue> #include <stdio.h> #include <iostream> #include <string.h> #include < Stdlib.h> #include <algorithm>using namespace std;typedef long long ll;typedef unsigned long long ull;const int in f=0x3f3f3f3f;const ll Inf=0x3f3f3f3f3f3f3f3fll;const int Maxn=18;int sx,sy,n,m,cnt,sum;int dir[4][2]={{0,1},{0,-1},{ 1,0},{-1,0}};int vis[maxn][maxn][16400];char str[maxn][maxn];struct edge{int x,y,step,flag,ss;}; struct snake{int x, y;} Sna[maxn*10];int bfs1 () {queue<edge>que; Edge C,ne; memset (vis,0,sizeof (VIS)); c.x=sx,c.y=sy,c.step=0;c.flag=0;c.ss=0; Vis[c.x][c.y][0]=1; Que.push (c); while (!que.empty ()) {C=que.front (); Que.pop (); if (c.flag==sum) return c.step; for (int i=0;i<4;i++) {int xx=c.x+dir[i][0]; int yy=c.y+dir[i][1]; if (xx<0| | xx>n-1| | yy<0| | yy>m-1| | str[xx][yy]== ' D ') continue; if (VIS[XX][YY][C.SS]) continue; Ne.x=xx;ne.y=yy;ne.step=C.STEP+1;NE.FLAG=C.FLAG;NE.SS=C.SS; if (str[xx][yy]== ' Y ') {for (int i=0;i<cnt;i++) {if (XX==SNA[I].X&&YY==SNA[I].Y) { if ((ne.ss>>i) &1) {break; }else{ne.ss+= (1<<i); ne.flag++; } break; }}} Vis[ne.x][ne.y][ne.ss]=1; Que.push (NE); }} return-1;} BOOL BFS (int PPP) {queue<edge>que; Edge C,ne; memset (vis,-1,sizeof (VIS)); c.x=sx,c.y=sy,c.step=0;c.flag=0;c.ss=0; Vis[c.x][c.y][0]=1; Que.push (c); while (!que.empty ()) {C=que.front (); Que.pop (); if (c.flag==sum) return 1; if (C.STEP==PPP) continue; for (int i=0;i<4;i++) {int xx=c.x+dir[i][0]; int yy=c.y+dir[i][1]; if (xx<0| | xx>n-1| | Yy<0|| yy>m-1| | str[xx][yy]== ' D ') continue; if (vis[xx][yy][c.ss]!=-1) {if (C.STEP+1<VIS[XX][YY][C.SS]) {ne.x=xx;ne.y=yy;ne.step=c. STEP+1;NE.FLAG=C.FLAG;NE.SS=C.SS; Vis[xx][yy][c.ss]=c.step+1,que.push (NE); }else continue; } NE.X=XX;NE.Y=YY;NE.STEP=C.STEP+1;NE.FLAG=C.FLAG;NE.SS=C.SS; if (str[xx][yy]== ' G ') {for (int i=0;i<cnt;i++) {if (XX==SNA[I].X&&YY==SNA[I].Y) { if ((ne.ss>>i) &1) {vis[ne.x][ne.y][ne.ss]=ne.step; Que.push (NE); Break }else{ne.ss+= (1<<i); Ne.step=0; Vis[xx][yy][ne.ss]=ne.step; Que.push (NE); NE.SS=C.SS; ne.step=c.step+1; Vis[xx][yy][ne.ss]=ne.step; Que.push (NE); } break; }}}} else if (str[xx][yy]== ' Y ') {for (int i=0;i<cnt;i++) { if (XX==SNA[I].X&&YY==SNA[I].Y) {if ((ne.ss>>i) &1) { Break }else{ne.ss+= (1<<i); ne.flag++; } break; }} Vis[ne.x][ne.y][ne.ss]=ne.step; Que.push (NE); } else{Vis[ne.x][ne.y][ne.ss]=ne.step; Que.push (NE); }}} return 0;} int main () {while (scanf ("%d%d", &n,&m)!=-1) {if (n==0&&m==0) break; cnt=0;sum=0; for (int i=0;i<n;i++) SCANF ("%s", Str[i]); for (int i=0;i<n;i++) {for (int j=0;j<m;j++) {if (str[i][j]== ' F ') sx=i,sy=j; if (str[i][j]== ' Y ') sum++; if (str[i][j]== ' Y ' | | str[i][j]== ' G ') {sna[cnt].x=i;sna[cnt++].y=j; }}} int ans=bfs1 (); if (ans==-1) {printf (" -1\n"); continue; } int Le=0,ri=ans; while (le<ri) {int mid= (LE+RI) >>1; if (BFS (mid)) Ri=mid; else le=mid+1; } printf ("%d\n", RI); } return 0;}
HDU 3681 BFS