HDU 2128 Tempter of the Bone II(BFS+状态压缩)

本文探讨了在8x8地图上的BFS搜索问题,采用了一种全新的状态表示方法来记录地图的访问状态,避免了传统方法中可能出现的状态遗漏或冗余。通过将整个地图的访问情况作为状态的一部分,有效地解决了复杂路径寻找问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:。。。

思路:

一开始, 我用 f[i][j][k] 表示在位置(i, j)有k个炸弹是否访问过。。

但是wa掉之后发现, 这个表示太大了,不能很好地刻画状态。。又想到加上 上一步的方向, 但是还是会把正确的状态给剪掉。。

既然, 数据是8x8, 为甚么不把整个map的访问状态保存下来呢?。。

参考了cxlove的blog

http://blog.youkuaiyun.com/acm_cxlove/article/details/7635497

______________________________________________________________________

再次思考BFS在隐式图上移动的情形。。。

在使用BFS时, 状态的表示决定了可以采取怎样的算法,剪枝等等。。。

//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <cassert>
#include <algorithm>
#include <cmath>
#include <climits>
#include <set>
#include <map>
using namespace std;

#define SPEED_UP iostream::sync_with_stdio(false);
#define FIXED_FLOAT cout.setf(ios::fixed, ios::floatfield);
#define rep(i, s, t) for(int (i)=(s);(i)<=(t);++(i))
#define urep(i, s, t) for(int (i)=(s);(i)>=(t);--(i))

typedef long long LL;

const int Maxn = 10;
const int Maxe = 580;
const int inf = INT_MAX/2;
const int dx[] = {1, -1, 0, 0};
const int dy[] = {0, 0, -1, 1};

char mm[Maxn][Maxn];
LL id[Maxn][Maxn];
int tot, sx, sy, ex, ey, m, n;

struct st {
    // x, y: position
    // t: time
    // s: state of map as bitset( 0 for not visited, 1 for visited)
    // a: amount of explosives
    int x, y, t;
    LL s;
    int a;
    st(int x, int y, int t, LL s, int a):x(x), y(y), t(t), s(s), a(a){}
    bool operator < (const st &rhs) const {
        return t > rhs.t;
    }
};

void init() {
    tot = 0;
    rep(i, 0, n-1) {
        cin >> mm[i];
        rep(j, 0, m-1) {
            char ch = mm[i][j];
            if (ch == 'S') {
                sx = i;sy = j;
            }
            else if (ch == 'D') {
                ex = i;ey = j;
            }
            id[i][j] = i*m+j;
        }
    }
}

void print(const st &i) {
    cout << "pos:" << i.x << ", " << i.y << " t: " << i.t << " a: " << i.a << " { ";
    rep(j, 0, 31)
        if ( (1<<j)&i.s ) cout << j << ' ';
    cout << "}\n";
}

#define BIT_ADD(s, i) ((s)|(1ll<<(i)))
#define BIT_HAS(s, i) ((s)&(1ll<<(i)))

int solve() {
    priority_queue<st> q;
    // t[x][y][k] 在 (x, y)有k个炸弹
    // 保存地图的状态
    set<LL> t[Maxn][Maxn][Maxe];

    q.push(st(sx, sy, 0, BIT_ADD(0ll, id[sx][sy]), 0));
    while (!q.empty()) {
        st fr = q.top();q.pop();
        if (t[fr.x][fr.y][fr.a].count(fr.s)) continue;
        t[fr.x][fr.y][fr.a].insert(fr.s);

        //print(fr);

        if (fr.x == ex && fr.y == ey) {
            return fr.t;
        }

        int nx, ny;
        char ch;
        rep(i, 0, 3) {
            nx = fr.x + dx[i];
            ny = fr.y + dy[i];
            if (0 <= nx && nx < n && 0 <= ny && ny < m) {
                ch = mm[nx][ny];
                if (ch == 'X') {
                    if ( BIT_HAS(fr.s, id[nx][ny]) )
                        q.push( st(nx, ny, fr.t+1, fr.s, fr.a) );
                    else if (fr.a) q.push( st(nx, ny, fr.t+2, BIT_ADD(fr.s, id[nx][ny]), fr.a-1) );
                }
                else if (isdigit(ch)) {
                    if ( BIT_HAS(fr.s, id[nx][ny]) )
                        q.push( st(nx, ny, fr.t+1, fr.s, fr.a) );
                    else
                        q.push( st(nx, ny, fr.t+1, BIT_ADD(fr.s, id[nx][ny]), fr.a+ch-'0') );
                }
                else {
                    q.push( st(nx, ny, fr.t+1, /*BIT_ADD(fr.s, id[nx][ny])*/fr.s, fr.a) );
                }
            }
        }
    }
    return -1;
}


int main() {
#ifndef ONLINE_JUDGE
    freopen("input.in", "r", stdin);
#endif
    SPEED_UP

    while (cin >> n >>m && (n && m)) {
        init();
        cout << solve() << endl;
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值