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;
}

 

posted @ 2013-05-10 15:58  心向往之  阅读(149)  评论(0)    收藏  举报