4 4 SX.. XX.. .... 1..D 4 4 S.X1 .... ..XX ..XD 0 0
-1 9
地图上有炸弹,可以炸掉墙壁。问最少几步能达到终点
状态压缩 地图除了起点和终点,有62个点,可以用状态压缩保存拿去炸弹和炸掉墙的状态
用容器标记,四维 状态,坐标,炸弹数
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<vector> #include<cmath> #define LL unsigned long long using namespace std; int n,m; char Map[10][10]; int Mp[10][10]; int dir[4][2]= {0,1,0,-1,1,0,-1,0}; int len; struct node { int x,y; int t; int boom; unsigned long long v; friend bool operator < (node a,node b) { return a.t>b.t; } bool cheak() { if(x>=0&&x<n&&y>=0&&y<m) return true ; return false ; } } st,ed; vector<unsigned long long>v[8][8][9*8*8+1];//标记 当前点拥有的炸弹数的状态 出现过则舍弃 bool cheak(node a) { for(int i=0; i<v[a.x][a.y][a.boom].size(); i++) if(a.v==v[a.x][a.y][a.boom][i]) return false ; return true ; } void bfs() { priority_queue<node>q; q.push(st); for(int i=0; i<8; i++) for(int j=0; j<8; j++) for(int l=0; l<8*8*9+1; l++) v[i][j][l].clear(); v[st.x][st.y][st.boom].push_back(st.v); while(q.size()) { st=q.top(); q.pop(); if(Map[st.x][st.y]=='D') { printf("%d\n",st.t); return ; } for(int i=0; i<4; i++) { ed=st; ed.t++; ed.x+=dir[i][0]; ed.y+=dir[i][1]; if(ed.cheak()) { if(Mp[ed.x][ed.y]>=0&&(ed.v&(1LL<<Mp[ed.x][ed.y]))==0) { if(Map[ed.x][ed.y]=='X') { if(ed.boom>0) { ed.boom--; ed.t++; ed.v|=(1LL<<Mp[ed.x][ed.y]); if(cheak(ed)) { v[ed.x][ed.y][ed.boom].push_back(ed.v); q.push(ed); } } } else { ed.boom+=Map[ed.x][ed.y]-'0'; ed.v|=(1LL<<Mp[ed.x][ed.y]); if(cheak(ed)) { v[ed.x][ed.y][ed.boom].push_back(ed.v); q.push(ed); } } } else { if(cheak(ed)) { v[ed.x][ed.y][ed.boom].push_back(ed.v); q.push(ed); } } } } } printf("-1\n"); return ; } int main() { while(cin>>n>>m) { if(n==0&&m==0) break; memset(Mp,-1,sizeof(Mp)); len=0; for(int i=0; i<n; i++) { for(int j=0; j<m; j++) { cin>>Map[i][j]; if(Map[i][j]=='X'||Map[i][j]>='0'&&Map[i][j]<='9') Mp[i][j]=len++; else if(Map[i][j]=='S') { st.x=i; st.y=j; st.t=0; st.boom=0; st.v=0; } } } bfs(); } return 0; }