题目链接HDU1429

解题思路:正常搜最短路的图,但是走过的路可能重复走,因为可能拿到钥匙后沿路返回。要有一个记录口袋中钥匙相应状态的数组,由于有“a-j”10把钥匙,可以用10位二进制的数将其状态压缩到这个数中0表示没有,1表示有。可以加一个步数即使走最短路也到达不了终点的剪枝。注意记录行走状态的数组book要提前标记,不能等到pop了才标记,不然会爆内存…(PS:这题题目没说清楚被魔王抓回去钥匙会不会清空,不过根据答案来看显然是清空的,如果钥匙不清空的话可能还可以不走,等魔王抓回去,再利用回到原点的便捷节省步数,或者说被抓回去刷新走的步数,从而寻求到最短的方案,这样的话,每次行走还要把此时直接回到原点的情况入队)


AC代码

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <map>
#include <stack>
#include <vector>
#include <utility>
using namespace std;

/* 1,容易想到的一个剪枝是总的步数的最短不够t的check掉 2, 不能多搜到到达t秒那一层,不然空间会超过 */

struct node {
    int x,y;
    int step;
    int have;
};

char graph[21][21];
int n,m,t;
int sx,sy,ex,ey;
int nex[4][2] = {0,1,1,0,0,-1,-1,0};
int book[21][21][1<<10]; //状态记录

queue<node> Q;

bool judge (int x, int y) {
    if(x<1 || x>n || y<1 || y>m || graph[x][y] == '*')
        return false;
    return true;
}

bool check (int x, int y, int step) {
    if(abs(ex - x) + abs(ey - y) < t - step)
        return false;
    return true;
}

int BFS() {
    int i;
    node tmp, now;

    while(!Q.empty()) {
        Q.pop();
    }
    now.x = sx;
    now.y = sy;
    now.step = 0;
    now.have = 0;
    Q.push(now);
    memset(book,0,sizeof(book));
    book[now.x][now.y][now.have] = 1;

    while(!Q.empty()) {
        now = Q.front();
        Q.pop();
        if(now.step < t && now.x == ex && now.y == ey) {
            return now.step;
        }
        if(check(now.x,now.y,now.step)) {
            continue;
        }

        for (i = 0; i < 4; i++) {
            tmp.x = now.x + nex[i][0];
            tmp.y = now.y + nex[i][1];
            tmp.step = now.step + 1;
            tmp.have = now.have;

            if(judge(tmp.x, tmp.y)) {
                if(graph[tmp.x][tmp.y] == '.' && book[tmp.x][tmp.y][tmp.have] == 0) {
                    Q.push(tmp);
                    book[tmp.x][tmp.y][tmp.have] = 1;
                }else {
                    if(graph[tmp.x][tmp.y] >= 'a' && graph[tmp.x][tmp.y] <= 'j') {
                        tmp.have |= (1<<(graph[tmp.x][tmp.y] - 'a'));
                        if(book[tmp.x][tmp.y][tmp.have] == 0) {
                            Q.push(tmp);
                            book[tmp.x][tmp.y][tmp.have] = 1;
                        }
                    }else if(graph[tmp.x][tmp.y] >= 'A' && graph[tmp.x][tmp.y] <= 'J' && ((1<<(graph[tmp.x][tmp.y] - 'A')) & tmp.have) != 0) {
                        if(book[tmp.x][tmp.y][tmp.have] == 0) {
                            Q.push(tmp);
                            book[tmp.x][tmp.y][tmp.have] = 1;
                        }
                    }
            }
        }
    }
    return -1;
}

int main() {
    int i,j;

    while(~scanf("%d%d%d",&n,&m,&t)) {
        getchar();
        for (i = 1; i <= n; i++) {
            for (j = 1; j <= m; j++) {
                scanf("%c", &graph[i][j]);
                if(graph[i][j] == '@') {
                    sx = i;
                    sy = j;
                    graph[i][j] = '.';
                }else if(graph[i][j] == '^') {
                    ex = i;
                    ey = j;
                    graph[i][j] = '.';
                }
            }
            getchar();
        }
        /* for (i = 1; i <= n; i++) { for (j = 1; j <= m; j++) { printf("%c",graph[i][j]); } printf("\n"); } printf("%d %d %d %d\n",sx,sy,ex,ey); */
        while(!Q.empty()) {
            Q.pop();
        }
        printf("%d\n",BFS());
    }
    return 0;
}