题意:给出一个图,$是宝藏的位置,图的边界上有一些入口,#代表没有没有炸药,A—Z代表炸药的数量,只能从一个入口进入,图中有一些数字代表石头,如果消耗一个炸药炸掉石头不花时间,不炸的话会消耗相应的时间,问最少到达宝藏地点的时间是多少。
思路:刚开始想着直接广搜,写了一会就觉得不行,如果到达一点有几条路径的时间相同,我们应该去携带炸药最多的,那样能保证后面的时间最少。所以把图增加成三维地图,记录到达每点携带的炸药数量的最短时间。
#include<iostream> #include<queue> using namespace std; const int N=110; const int inf=0x3fffffff; int dir[4][2]={0,1,0,-1,1,0,-1,0},n,m,t[N][N][27]; bool vis[N][N][27]; char map[N][N]; struct node { int x,y,k; }cur,next; bool judge(int x,int y) { if(x<0||x>=n||y<0||y>=m||map[x][y]=='*')return false; return true; } void bfs() { int i,j,x,y,ii,k,sx,sy,ans=inf; queue<node>Q; for(i=0;i<n;i++) { for(j=0;j<m;j++) { for(ii=0;ii<27;ii++) t[i][j][ii]=inf,vis[i][j][ii]=false; if(map[i][j]=='$') sx=i,sy=j; else if(map[i][j]=='#'||map[i][j]>='A'&&map[i][j]<='Z') { cur.x=i;cur.y=j; if(map[i][j]=='#')cur.k=0; else cur.k=map[i][j]-'A'+1; Q.push(cur); map[i][j]='*';t[i][j][cur.k]=0;vis[i][j][cur.k]=true; } } } while(!Q.empty()) { cur=Q.front();Q.pop(); vis[cur.x][cur.y][cur.k]=false; for(i=0;i<4;i++) { next.x=x=cur.x+dir[i][0]; next.y=y=cur.y+dir[i][1]; next.k=k=cur.k; if(!judge(x,y))continue; if((map[x][y]=='.'||map[x][y]=='$')&&t[x][y][k]>t[cur.x][cur.y][k])//直接走过 { t[x][y][k]=t[cur.x][cur.y][k]; if(!vis[x][y][k]){Q.push(next);vis[x][y][k]=true;} } else if(map[x][y]>='1'&&map[x][y]<='9') { int temp=map[x][y]-'0'; if(t[x][y][k]>t[cur.x][cur.y][k]+temp)//不炸 { t[x][y][k]=t[cur.x][cur.y][k]+temp; if(!vis[x][y][k]){Q.push(next);vis[x][y][k]=true;} } if(k>0&&t[x][y][k-1]>t[cur.x][cur.y][k])//炸 { next.k--; t[x][y][k-1]=t[cur.x][cur.y][k]; if(!vis[x][y][k-1]){Q.push(next);vis[x][y][k-1]=true;} } } } } for(i=0;i<27;i++) if(ans>t[sx][sy][i]){ans=t[sx][sy][i];} if(ans<inf)printf("%d\n",ans); else printf("IMPOSSIBLE\n"); } int main() { n=0; while(gets(map[n]),map[n][0]!='-') { if(map[n][0]=='\0') { m=strlen(map[0]); bfs();n=-1; } n++; } return 0; }