Poweroj:来自学长的善意:ZQ的杀龙之旅(状压BFS)

传送门:https://www.oj.swust.edu.cn/problem/show/2794

来自学长的善意:ZQ的杀龙之旅

Time Limit: 15000 MS Memory Limit: 65536 KB
Total Submit: 56 Accepted: 15 Page View: 127

Description

在西科大龙山上封印着一条邪恶的黑龙,不久即将苏醒,传说如果集齐所有的正义之剑,就可以再次封印黑龙
正义的骑士ZQ,为了封印黑龙,走上了寻找正义之剑的旅程。。。。
为了简化问题我们把整个世界看成一个n行m列的二维平面,在这个平面内只会存在下面几种符号:
“I” 代表ZQ当前的位置。
“O” 代表黑龙的位置。
“X” 代表障碍物。
“_” 代表正常的道路
“+” 代表一把正义之剑。
由于ZQ腿比较短,他只能一次花费一天的时间移动到他的相临(上下左右)的位置
由于时间原因他需要尽快的封印黑龙,因此他需要知道最少需要多少天可以封印黑龙。

Input

第一行三个整数n(1<=n<=100),m(1<=m<=100),k(0<=k<=10),分别代表地图的行数,列数,正义之剑的把数;
然后,n行,每行m个字符代表地图的信息;

Output

输出一个整数,代表最少需要多少天XQ能封印黑龙,如果不能封印黑龙,则输出-1。

Sample Input

3 3 1
I_X
__O
__+

Sample Output

5


解题心得:

  1. 这个题是给学弟出新生赛的时候出的,当时叫CHY他们出一个BFS,结果他们弄了这个状压标记路径的BFS,弄得数据也十分不友善,删了一半多的数据程序都要跑十秒左右才能出来。比赛的时候场面十分尴尬。
  2. 思路还是比较简单的,唯一的难点就是正义之剑很多,去拿剑路径不可能简单的标记,那么考虑一下怎么才不算重复走,假如给每一把剑标记一个数字,重复走就只存在拿了相同组合的剑然后走之前拿了同样组合的剑走过的路。那么最多十把剑可能有多少种组合情况呢。2^10种,就可以用二进制表示,给剑标号,如果这个剑拿到了,那么代表这个剑的二进制位上面就用1来表示。然后正常标记,只有全为1的状态再走到龙所在的地方才算结束搜索。

#include <algorithm>
#include <queue>
#include <stdio.h>
using namespace std;
const int maxn = 110;

char maps[maxn][maxn];
bool vis[maxn][maxn][1<<11];
int n,m,k,all_x;
int dir[4][2] = {0,1,0,-1,1,0,-1,0};

struct Node {
    int x,y,path,time;
}now,Next;

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

void init() {
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)
        scanf("%s",maps[i]+1);
    int cnt = 0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++) {
            if(maps[i][j] == '+') {
                maps[i][j] = '0' + cnt++;//给每一把剑标号
            }
            if(maps[i][j] == 'I') {
                now.x = i;
                now.y = j;
                now.path = 0;
                now.time = 0;
            }
        }
    all_x = (1<<k)-1;//最终拿到所有剑的状态
}

int bfs() {
    queue <Node> qu;
    qu.push(now);
    while(!qu.empty()) {
        now = qu.front();
        qu.pop();
        for(int i=0;i<4;i++) {
            int x = now.x + dir[i][0];
            int y = now.y + dir[i][1];
            if(check(x,y))
                continue;
            Next.path = now.path;
            Next.time = now.time + 1;
            Next.x = x; Next.y = y;
            if(maps[x][y] >= '0' && maps[x][y] <= '9')
                Next.path |= (1 << (maps[x][y] - '0'));
            if(maps[x][y] == 'O' && Next.path == all_x)
                return Next.time;
            if(vis[x][y][Next.path])
                continue;
            vis[x][y][Next.path] = true;
            qu.push(Next);
        }
    }
    return -1;
}

int main() {
    init();
    int ans = bfs();
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/GoldenFingers/p/9107109.html