hdu 5025

这题从昨天做到今天,各种错误。以前做过类似的题,是用状态压缩保存当前拥有钥匙的状态,看到这题毫不犹豫的写了。开标记数组的时候,因为钥匙最多有9把,1<<9再加上地图和蛇,发现开不下这么大。就各种剪支,然后又发现这题因为有蛇的存在,bfs第一次得到的答案并不是最优解,还得跑完整个队列才行,各种问题,一直GG。然后发现这题的钥匙必须按照顺序来拿,所以用不着状态压缩。把杀死蛇的状态压缩后,只用开1<<5 开的下,于是开4维标记数组的bfs就可以写了。(中间不想跑完整个队列,所以重载结构体后用优先队列,这样也不行)

存图时预先把图中的蛇处理成1-5的数字,这些技巧看了别人的,学到了学到了。

    #include <iostream>  
    #include <cstdio>  
    #include <cstring>  
    #include <queue>  
    #include <algorithm>  
      
    using namespace std;  
    int dir[4][2] = {1,0,-1,0,0,1,0,-1}; 
    const int inf = 1<<20;  
    const int maxn = 105;   
    char g[maxn][maxn];  
    int d[maxn][maxn][10][33];  
    int n, m, sn;  
    int sx, sy;  
    struct node{  
        int x, y, k, s, d;  
        node(int xx, int yy, int kk, int ss, int dd):x(xx),y(yy),k(kk),s(ss),d(dd) { 
        }  
    };  
      
    void init() {  
        sn = 0;  
        memset(g, 0, sizeof(g));  
        memset(d, -1, sizeof(d));  
        for (int i = 1; i <= n; i++) {  
            for (int j = 1; j <= n; j++) {  
                scanf("%c", &g[i][j]);  
                if (g[i][j] == 'S') {  
                    g[i][j] = 'A' + sn;  
                    sn++;  
                }  
                if (g[i][j] == 'K') {  
                    sx = i;   
                    sy = j;  
                }  
            }  
            getchar();  
        }  
    }  
    void bfs(int x, int y, int key, int snum) {  
        queue<node> q;  
        while (!q.empty())   
            q.pop();  
        int ans = inf;  
        node start(x, y, key, snum, 0);  
        q.push(start);  
      
        while (!q.empty()) {  
            node tmp = q.front();   
            q.pop();  
            x = tmp.x;   
            y = tmp.y;  
            key = tmp.k;  
            snum = tmp.s;  
      
            if (key == m && g[x][y] == 'T')   
              {  ans = min(ans, tmp.d); continue;}  
      
            if (d[x][y][key][snum] != -1)  
                continue;  
            d[x][y][key][snum] = tmp.d;  
      
            for (int i = 0; i < 4; i++) {  
                int tx = x + dir[i][0];  
                int ty = y + dir[i][1];  
                int st = g[tx][ty] - 'A';  
                if (st >= 0 && st < sn) {  
                    if (snum & (1 << st))           
                        q.push(node(tx, ty, key, snum, tmp.d + 1));  
                    else  
                        q.push(node(tx, ty, key, (snum | (1 << st)), tmp.d + 2));   
                }   
                else if (g[tx][ty] == '1' + key)   
                    q.push(node(tx, ty, key + 1, snum, tmp.d + 1));   
                else if (g[tx][ty] >= '1' && g[tx][ty] < '1' + m)   
                    q.push(node(tx, ty, key, snum, tmp.d + 1));   
                else if (g[tx][ty] == '.' || g[tx][ty] == 'K' || g[tx][ty] == 'T')   
                    q.push(node(tx, ty, key, snum, tmp.d + 1));    
            }   
        }  
        if(ans!=inf) printf("%d\n",ans);
        else printf("impossible\n");
    }
    int main() {  
        while (scanf("%d %d", &n, &m) && (n || m)) {  
            getchar();  
            init();
            bfs(sx, sy, 0, 0);  
        }  
        return 0;  
    }  


好题,因为太菜,所以超耐磨!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值