5 5 GDDSS SSSFS SYGYS SGSYS SSYSS 0 0
4
2010 Asia Hangzhou Regional Contest
题意:一个人背着一个有一定容量的电池,每走一步耗用1,D:不能走,S:空地 ,G:能量池,把背的容量电池充满(只能用一次)可取可不取,F:走点,Y:开关,这个人必须全部关闭开关才能走出地牢,问最小背多大的容量电池才能走出。
注意:在一个位置,虽然某一个状态走过了,但当前剩余能量比前一次走过的能量大,则也要放入队列中。
解题:先求出最大容量,不用管G,再用二分+bfs出最小须要的容量。
#include<iostream>
#include<queue>
using namespace std;
typedef struct nnn
{
int x,y,G,Y,st;
}node;
char map[16][16];
int vist[16][16][1<<16];
int n,m,sta_y,k,sx,sy,dir[4][2]={0,1,0,-1,1,0,-1,0},tmap[16][16];
void init()
{
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
for(int s=0;s<(1<<k);s++)
vist[i][j][s]=-1;
}
int bfs()
{
if(sta_y==0)return 0;
queue<node>q;
node p,pp;
init();
p.x=sx; p.y=sy; p.Y=0; p.st=0;
vist[sx][sy][0]=1;
q.push(p);
while(!q.empty())
{
p=q.front(); q.pop();
for(int e=0;e<4;e++)
{
int tx,ty;
tx=p.x+dir[e][0]; ty=p.y+dir[e][1];
if(tx>=0&&tx<n&&ty>=0&&ty<m&&map[tx][ty]!='D')
{
pp.x=tx; pp.y=ty; pp.st=p.st+1; pp.Y=p.Y;
if(map[tx][ty]=='Y')pp.Y|=(1<<tmap[tx][ty]);
if(pp.Y==sta_y)return pp.st;
if(vist[tx][ty][pp.Y]==-1)
q.push(pp),vist[tx][ty][pp.Y]=1;
}
}
}
return -1;
}
int bfs1(int maxst)
{
queue<node>q;
node p,pp;
init();
p.x=sx; p.y=sy; p.G=0; p.Y=0; p.st=maxst;
vist[sx][sy][0]=maxst;//注意
q.push(p);
while(!q.empty())
{
p=q.front(); q.pop();
for(int e=0;e<4;e++)
{
int tx,ty;
tx=p.x+dir[e][0]; ty=p.y+dir[e][1];
if(tx>=0&&tx<n&&ty>=0&&ty<m&&map[tx][ty]!='D')
{
pp.x=tx; pp.y=ty; pp.st=p.st-1; pp.Y=p.Y; pp.G=p.G;
if(map[tx][ty]=='Y')
{
pp.Y|=(1<<tmap[tx][ty]);
if(pp.Y==sta_y)return 1;
}
else if(map[tx][ty]=='G')
{
if((pp.G&(1<<tmap[tx][ty]))==0)
{
pp.G|=(1<<tmap[tx][ty]); pp.st=maxst;
if(vist[tx][ty][pp.G|pp.Y]<maxst)//注意
q.push(pp); vist[tx][ty][pp.G|pp.Y]=maxst;
}
pp.G=p.G; pp.st=p.st-1;
}
if(pp.st&&vist[tx][ty][pp.G|pp.Y]<pp.st)//注意
q.push(pp),vist[tx][ty][pp.G|pp.Y]=pp.st;
}
}
}
return 0;
}
int main()
{
int minst;
while(scanf("%d%d",&n,&m)>0&&m+n!=0)
{
for(int i=0;i<n;i++)scanf("%s",map[i]);
k=0; sta_y=0;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(map[i][j]=='G')
{
tmap[i][j]=k; k++;
}
else if(map[i][j]=='Y')
{
tmap[i][j]=k; sta_y|=(1<<k); k++;
}
else if(map[i][j]=='F')
sx=i,sy=j;
minst=bfs();
if(minst<=1)
{
printf("%d\n",minst);continue;
}
int l,mm;
l=1;
while(l<minst)
{
mm=(l+minst)/2;
if(bfs1(mm)==1)minst=mm;
else l=mm+1;
}
printf("%d\n",minst);
}
}
原文地址:http://blog.csdn.net/u010372095/article/details/39006949