题意:机器人有一个初始能量x,每走到G点时可选择充满能量(初始能量是满的),每走一步消耗一点能量,问当x最小为多少时,可以把所有的Y都走一遍,输出最小的x!
注意:G点和Y点加一起最多15个
注意:G点和Y点加一起最多15个
附ac代码
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
char map[16][16];
int dp[1<<16][16],dis[16][16];
int tot[16][2];
int cnt,first,n,m,ans;
int mark[16][16];
int dui[4][2]={0,1,0,-1,1,0,-1,0};
int min(int a,int b)
{
if(a<b)
return a;
return b;
}
int max(int a,int b)
{
if(a>b)
return a;
return b;
}
struct node{
int x,y,time;
}cur,next;
int bfs(int x1,int y1,int x2,int y2)
{
memset(mark,0,sizeof(mark));
queue<node>q;
cur.x=x1;
cur.y=y1;
cur.time=0;
while(!q.empty())
q.pop();
q.push(cur);
while(!q.empty())
{
cur=q.front();
q.pop();
for(int i=0;i<4;i++)
{
next.x=cur.x+dui[i][0];
next.y=cur.y+dui[i][1];
next.time=cur.time+1;
if(map[next.x][next.y]=='D')
continue;
if(next.x>=n||next.y>=m||next.x<0||next.y<0)
continue;
if(next.x==x2&&next.y==y2)
return next.time;
if(mark[next.x][next.y])
continue;
mark[next.x][next.y]=1;
q.push(next);
}
}
return -1;
}
int fun(int kkk)
{
memset(dp,-1,sizeof(dp));
int i,j;
dp[1<<first][first]=kkk;
//printf("ans=%d\n",ans);
for(i=0;i<(1<<cnt);i++)
{
for(j=0;j<cnt;j++)
{
if(i&(1<<j)==0)continue;
if((i&ans)==ans&&dp[i][j]!=-1)
return 1;
for(int k=0;k<cnt;k++)
{
if(k==j)
continue;
if(((1<<k)&i))
continue;
int tem=dp[i][j]-dis[j][k];
if(tem<0)
continue;
if(dis[j][k]==-1)
continue;
if(dp[i][j]==-1)
continue;
dp[i+(1<<k)][k]=max(tem,dp[i+(1<<k)][k]);
if(map[tot[k][0]][tot[k][1]]=='G')
dp[i+(1<<k)][k]=kkk;
int l=i+(1<<k);
if(dp[l][k]!=-1)
{
if((l&ans)==ans)
return 1;
}
}
}
}
return 0;
}
int main()
{
int i,j;
while(scanf("%d%d",&n,&m)!=EOF)
{ans=0;cnt=0;
if(n==0&&m==0)
break;
for(i=0;i<n;i++)
{
scanf("%s",map[i]);
for(j=0;j<m;j++)
{
if(map[i][j]=='Y')
{
tot[cnt][0]=i;
tot[cnt][1]=j;
ans+=(1<<cnt);
cnt++;
}
if(map[i][j]=='F')
{
first=cnt;
tot[cnt][0]=i;
tot[cnt][1]=j;
ans+=(1<<cnt);
cnt++;
}
if(map[i][j]=='G')
{
tot[cnt][0]=i;
tot[cnt][1]=j;
cnt++;
}
}
}
memset(dis,-1,sizeof(dis));
for(i=0;i<cnt;i++)
{
for(j=0;j<cnt;j++)
{
if(i==j)
dis[i][j]=0;
else
dis[i][j]=bfs(tot[i][0],tot[i][1],tot[j][0],tot[j][1]);
}
}
int l=1,r=225;
int aaa=1<<30;
while(l<=r)
{
int mid=(l+r)/2;
if(fun(mid))
{
r=mid-1;
aaa=min(ans,mid);
}
else
l=mid+1;
}
if(aaa==(1<<30))
printf("-1\n");
else
printf("%d\n",aaa);
}
return 0;
}