HDU 4771 Stealing Harry Potter's Precious

原文链接: HDU 4771 Stealing Harry Potter's Precious

上一篇: HDU 1242 bfs

下一篇: HDU 1429 bfs 状态压缩

题意:

给定n*m的地图

#为墙 @为起点

下面K个坐标

问:遍历K个给定坐标,需要的最小步数

思路:

因为K 最大只有4

状压 当前是否走过某点

用二进制 的 i 位 0、1表示 第i个点是否走过

也可以初始化宝藏为1<<i,这样判断和赋值会方便一点

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

#define LL long long
int const MAX = 111;
int const INF = 1 << 30;
using namespace std;

int mp[MAX][MAX], n, m, k;
char tmp[MAX];

//vis[x][y][s] 表示经过x,y点,状态s
bool vis[MAX][MAX][20];
struct Node {
    int x, y, step, state;
    Node(int x = 0, int y = 0, int state = 0, int step = 0) : x(x), y(y), step(step), state(state){ }
};


int dir[4][2] = { 1, 0, -1, 0, 0, 1, 0, -1 };

void setvis(Node nd){
    vis[nd.x][nd.y][nd.state] = 1;
}
int bfs(Node st){
    queue<Node> q;
    q.push(st);
    setvis(st);
    while(!q.empty()){
        Node t = q.front();
        q.pop();
        // printf("(%d %d %d %d )\n", t.x, t.y, t.state, t.step);
        if(t.state == ( 1 << k ) - 1){
            return t.step;
        }

        for(int k = 0 ; k < 4 ; k++){
            int nx = t.x + dir[k][0], ny = t.y + dir[k][1], ns;
            if(nx < 1 || nx > n || ny < 1 || ny > m || mp[nx][ny] == -1)
                continue;
            if(mp[nx][ny] == 0)
                ns = t.state;
            else
                ns = t.state | 1 << ( mp[nx][ny] - 1 );
            if(vis[nx][ny][ns] == 0){
                q.push(Node(nx, ny, ns, t.step + 1));
                setvis(Node(nx, ny, ns));
            }
        }

    }
    return -1;
}
int main(int argc, char* argv[]){
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);


    while(scanf("%d %d", &n, &m) != EOF && ( n || m )){
        //出发节点
        Node st;
        for(int i = 1 ; i <= n ; i++){
            scanf("%s", tmp + 1);
            for(int j = 1 ; j <= m ; j++){
                mp[i][j] = tmp[j] == '#' ? -1 : 0;
                if(tmp[j] == '@')
                    st.x = i, st.y = j, st.step = st.state = 0;
            }
        }
        int x, y;
        scanf("%d", &k);

        for(int i = 1 ; i <= k ; i++){
            scanf("%d %d", &x, &y);
            mp[x][y] = i;
        }
        /*
           //输出迷宫,0可走,-1障碍,1-k是宝藏同时也是编号
           printf("st:(%d,%d)\n", st.x, st.y);
           for(int i = 1 ; i <= n ; i++)
            for(int j = 1 ; j <= m ; j++)
                printf("%d%c", mp[i][j], j == m ? '\n' : ' ');
         */
        memset(vis, 0, sizeof( vis ));
        printf("%d\n", bfs(st));
    }


    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值