参看bfs的一般格式
695. 岛屿的最大面积
bfs:在最短路径上,我们最多只会经过每个房间一次。因此从起点开始,使用队列进行广度优先搜索,当第一个搜索到某个节点的时候,我们就可以得到从起点到该节点正确的最短路。
本题目的关键在于:在最短路径上也不可能存在如下的情况:我们经过了某个房间两次,并且这两次我们拥有钥匙的情况是完全一致的。
所以我们使用dist[x][y][mask]
来存储每个位置的状态,xy表示位置,mask是使用位运算存储钥匙状态,dist==-1时这一格子从未走过,否则存储的是到目前走过的格子数量。
class Solution {
public:
int shortestPathAllKeys(vector<string>& grid) {
map<char,int> keytoindex;
int sx=0,sy=0,nx,ny;
int row=grid.size(),col=grid[0].size();
int tempi;
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(grid[i][j]=='@'){
sx=i;sy=j;
}
else if(islower(grid[i][j])){
if(!keytoindex.count(grid[i][j])){
tempi=keytoindex.size();
keytoindex[grid[i][j]]=tempi;
}
}
}
}
// for(auto [k,v]:keytoindex){
// cout<<k<<" "<<v<<endl;
// }cout<<endl;
int cx=sx,cy=sy;
vector<vector<vector<int>>> dist(row,vector<vector<int>>(col,vector<int>(1<<keytoindex.size(),-1)));
const int dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
queue<tuple<int,int,int>> bq;
bq.emplace(cx,cy,0);
dist[sx][sy][0]=0;
while(!bq.empty()){
auto [cx,cy,mask]=bq.front();
bq.pop();
for(int i=0;i<4;i++){
nx=cx+dir[i][0];
ny=cy+dir[i][1];
if(((0<=nx&&nx<row) && (0<=ny&&ny<col)) && grid[nx][ny]!='#'){
if(grid[nx][ny]=='@' || grid[nx][ny]=='.'){
if(dist[nx][ny][mask]==-1){
dist[nx][ny][mask]=dist[cx][cy][mask]+1;
bq.emplace(nx,ny,mask);
}
}
else if(islower(grid[nx][ny])){
int newmask=mask | (1<<keytoindex[grid[nx][ny]]);
if(dist[nx][ny][newmask]==-1){
dist[nx][ny][newmask]=dist[cx][cy][mask]+1;
if(newmask==((1<<keytoindex.size())-1)){
return dist[nx][ny][newmask];
}
bq.emplace(nx,ny,newmask);
}
}
else{
if(mask & 1<<keytoindex[tolower(grid[nx][ny])] && dist[nx][ny][mask]==-1 ){
dist[nx][ny][mask]=dist[cx][cy][mask]+1;
bq.emplace(nx,ny,mask);
}
}
}
}
}
return -1;
}
};
注意杂项:
1. << >>左移右移运算的优先级低于加减±
2. 注意观察此处dist初始化的时候的预留空间如何书写。
数据类型(个数,子数据数据类型)
数据类型(个数,子数据的值)
vector<vector<vector<int>>> dist(
row,vector<vector<int>>(
col,vector<int>(
1<<keytoindex.size(),-1
)
)
);