hdu 2128 广搜
题意:m×n的迷宫, ‘S’ 起点 ‘D' 终点 '.' 可以走 ‘X’ 墙 ‘1’~‘9’炸弹的数量,往上下左右走一步花费1秒钟,炸一面墙多花1秒钟,问最少多长时间能走到终点。
分析:迷宫最大为8×8,可以用一个long long表示状态,走过的地方为1,没走过的为0. 然后广搜...
判重用的map[64],map[i][state]表示在第i个格子,状态为state所用的最少时间。
如果只用一个map 同时存储第 i 个格子和状态state,会超时。
另外state第50位置1不能用 state |= 1<<50, 1默认int型,左移50位是0, 要state |= (ULL)1<<50 或 state |= 1ULL<<50.
int dx[] = {-1,0,1,0};//up Right down Left int dy[] = {0,1,0,-1}; const int M = 100005; ULL s[M]; int pos[M],Time[M],cnt[M],p,t; struct cmp{ bool operator()(int a,int b){ return Time[a]>Time[b]; } }; priority_queue<int,vector<int>,cmp> q; int n,m,ans; ULL l=1; char c[70]; map<LL, int> mp[64]; map<LL, int>::iterator it; void push(){ int i=pos[p]; it = mp[i].find(s[p]); if(it != mp[i].end()&& (*it).second <= Time[p] ) return; mp[i][ s[p] ] = Time[p]; q.push(p); p++; } void bfs(){ while(!q.empty()){ t=q.top(); q.pop(); int x=pos[t]/m, y=pos[t]%m; FOR(i,0,4){ int xx=x+dx[i],yy=y+dy[i]; if(xx<0||xx>=n||yy<0||yy>=m)continue; int next = xx * m + yy; //if(Time[t]>200)return; if(c[next] == 'D') {checkmin(ans,Time[t]+1); return;} if((l<<next) & s[t]){ s[p]=s[t]; pos[p]=next; Time[p]=Time[t]+1; cnt[p]=cnt[t]; push(); }else{ if(c[next] == 'X'){ if(cnt[t]){ s[p]=s[t]|(l<<next); pos[p]=next; Time[p]=Time[t]+2; cnt[p]=cnt[t]-1; push(); } }else if(c[next]>='1'&&c[next]<='9'){ s[p]=s[t]|(l<<next); pos[p]=next; Time[p]=Time[t]+1; cnt[p]=cnt[t]+c[next]-'0'; push(); } } } } } int main(){ #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); #endif while(cin>>n>>m,n){ ans=-1; int x=0; ULL state=0; FOR(i,0,n) FOR(j,0,m) { int r = i * m + j; cin>>c[r]; if(c[r]=='S'){ state |= (1ULL<<r); x = r;} else if(c[r] == '.' || c[r] == 'D') state |= (1ULL<<r); } while( !q.empty() )q.pop(); FOR(i,0,64)mp[i].clear(); p=0; s[p]=state; pos[p]=x; Time[p]=0; cnt[p]=0; q.push(p); mp[x][state]=0; p++; bfs(); cout<<ans<<endl; } return 0; }