题意:机器人有一个初始能量x,每走到G点时可选择充满能量(初始能量是满的),每走一步消耗一点能量,问当x最小为多少时,可以把所有的Y都走一遍,输出最小的x!
注意: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; }
时间: 2024-10-15 22:00:58