HDU - 5067 Harry And Dig Machine (bfs + 状态压缩)

来源:互联网 发布:农村淘宝黄岩服务中心 编辑:程序博客网 时间:2024/05/21 20:44

题目大意:有一个n*m的网格,网格上面有k个地方有石头,现在要求从左上角出发,遍历所有有石头的地方,然后回到左上角,问最短距离是多少

解题思路:因为石头的总数小于等于10,所以可以进行压缩
设dp[i][j][state]表示在(i,j)位置,遍历的石头状态为state,走的最小距离,直接bfs即可

#include <cstdio>#include <cstring>#include <algorithm>#include <map>#include <queue>using namespace std;#define N 55#define S (1<<11)#define INF 0x3f3f3f3fstruct Node {    int x, y, state, step;}start;map<int, int> M;int n, m, stone_num;int dp[N][N][S], g[N][N];int dir[4][2] = {{-1,0}, {1,0}, {0, -1}, {0,1}};void init() {    M.clear();    stone_num = 0;    for (int i = 0; i < n; i++)        for (int j = 0; j < m; j++) {            scanf("%d", &g[i][j]);            if (g[i][j])                    M[i * m + j] = stone_num++;        }    memset(dp, 0, sizeof(dp));}int bfs() {    queue<Node> q;    start.x = 0;    start.y = 0;    if (g[0][0])        start.state = (1 << M[0]);    else        start.state = 0;    start.step = 0;    q.push(start);    while (!q.empty()) {        Node t = q.front();        q.pop();        int x = t.x, y = t.y;        if (x == 0 && y == 0 && t.state == (1 << stone_num) - 1) {            break;        }        for (int i = 0; i < 4; i++) {            int xx = x + dir[i][0];            int yy = y + dir[i][1];            int state = t.state;            int step = t.step;            if (xx < 0 || yy < 0 || xx >= n || yy >= m )                continue;            if (g[xx][yy])                state |= (1 << M[xx * m + yy]);            if (dp[xx][yy][state])                continue;            dp[xx][yy][state] = step + 1;            Node tt;            tt.x = xx;            tt.y = yy;            tt.state = state;            tt.step = t.step + 1;            q.push(tt);        }    }    return dp[0][0][(1 << stone_num) - 1];}int main() {    while (scanf("%d%d", &n, &m) != EOF) {        init();        if(stone_num == 0)            printf("0\n");        else            printf("%d\n", bfs());    }    return 0;}

上面是我复杂化了,其实只是状态压缩而已,只需要计算一下每种状态的转移就可以了,不需要一格格的走。。。

#include <cstdio>#include <cstring>#include <cstdlib>#include <queue>using namespace std;#define S (1 << 11)#define N 20#define INF 0x3f3f3f3fstruct Stone {    int x, y;}stone[N];struct Node {    int state, pos;}start;int n, m;int dp[S][N], cnt;void init() {    int x;    cnt = 1;    stone[0].x = 0;    stone[0].y = 0;    for (int i = 0; i < n; i++)        for (int j = 0; j < m; j++) {            scanf("%d", &x);            if(x) {                stone[cnt].x = i;                stone[cnt++].y = j;            }        }}int dis(int i, int j) {    return abs(stone[i].x - stone[j].x) + abs(stone[i].y - stone[j].y);}void solve() {    memset(dp, 0x3f, sizeof(dp));    queue<Node> q;    start.state = 1;    start.pos = 0;    q.push(start);    dp[1][0] = 0;    while (!q.empty()) {        Node t = q.front();        q.pop();        int state = t.state;        int pos = t.pos;        for (int i = 1; i < cnt; i++) {            if (!(state & (1 << i))) {                if ((state | (1 << i)) == (1 << cnt) - 1) {                    dp[state | (1 << i)][i] = min(dp[state | (1 << i)][i], dp[state][pos] + dis(pos,i) + dis(0,i));                }                else {                    if(dp[state | (1 << i)][i] > dp[state][pos] + dis(pos, i)) {                        dp[state | (1 << i)][i] = dp[state][pos] + dis(pos, i);                        Node tt;                        tt.state = state | (1 << i);                        tt.pos = i;                        q.push(tt);                    }                }            }        }    }    int ans = INF;    for(int i = 1; i < cnt; i++)        ans = min(ans, dp[(1 << cnt) - 1][i]);    printf("%d\n", ans);}int main() {    while(scanf("%d%d", &n, &m) != EOF) {        init();        if(cnt == 1)            printf("0\n");        else            solve();    }    return 0;}
0 0