CSL的校园卡-状态压缩+bfs

# csl的校园卡

题目:

今天是阳光明媚,晴空万里的一天,CSL早早就高兴地起床走出寝室到校园里转悠。

但是,等到他回来的时候,发现他的校园卡不见了,于是他需要走遍校园寻找它的校园卡。CSL想要尽快地找回他掉的校园卡,于是便求助于OneDay帮他一起找。

OneDay和CSL在同一已知的地点出发,并以相同的速度(1格/秒)搜索校园,试求两人走遍校园的最短时间。

Input
第一行为两个整数n,m(1≤n,m≤4),表示地图的大小。接下来是n行m列的地图:X表示障碍物,S表示起点,O表示空地。障碍物不能直接经过,数据保证所有空地是可达的,起点有且只有一个。

Output
输出一个整数表示两人共同走遍校园所需的最少时间。

思路:

建立数组vis[id][x1][y1][x2][y2],id为走过的路径,压缩为一个值,x1表示A的当前x坐标,y1表示A的当前y坐标,x2表示B的当前x坐标,y2表示B的当前y坐标。对两个点进行bfs即可,注意计算路径id值时应该用或|进行计算。当id等于结束值时返回结果。

代码:

#include <iostream>
#include <algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#define INF 0x3f3f3f3f
using namespace std;
int m, n;
char map[10][10];
struct node
{
    int x1, y1;
    int x2, y2;
    int t;
    int id;
}s;
bool vis[(1 << 16) + 1][5][5][5][5];
queue<node> q;
int dir[4][2] = { 1,0,-1,0,0,1,0,-1 };
int bfs(int end)
{
    q.push(s);
    vis[s.id][s.x1][s.y1][s.x2][s.y2] = true;
    while (!q.empty())
    {
        node t = q.front();
        q.pop();
        if (t.id==end)
        {
            return t.t;
        }
        for (int i = 0; i < 4; i++)
        {
            int nx = t.x1 + dir[i][0], ny = t.y1 + dir[i][1];
            if (nx >= 0 && ny >= 0 && nx < n && ny < m&&map[nx][ny]!='X')
            {
                for (int j = 0; j < 4; j++)
                {
                    int n1x = t.x2 + dir[j][0], n1y = t.y2 + dir[j][1];
                    if (n1x >= 0 && n1y >= 0 && n1x < n && n1y < m&&map[n1x][n1y]!='X')
                    {
                        int newid;
                        newid = (t.id | (1 << (nx*m + ny))) | 1 << ((n1x*m + n1y));
                        if (vis[newid][nx][ny][n1x][n1y])
                            continue;
                        vis[newid][nx][ny][n1x][n1y] = true;
                        node b;
                        b.x1 = nx, b.y1 = ny;
                        b.x2 = n1x, b.y2 = n1y;
                        b.t = t.t + 1;
                        b.id = newid;
                        q.push(b);
                    }
                }
            }
        }
    }
}
int main()
{
    memset(vis, false, sizeof vis);
    scanf("%d %d", &n, &m);
    int end = 0;
    for (int i = 0; i < n; i++)
    {
        scanf("%s", &map[i][0]);
        for (int j = 0; j < m; j++)
        {
            if (map[i][j] == 'S')
                s.x1 =s.x2= i, s.y1=s.y2 = j, end += 1 << (i*m + j);
            if (map[i][j] == 'O')
                end += 1 << (i*m + j);
        }
    }
    s.t = 0;
    s.id = 1<<(s.x1*m+s.y1);
    printf("%d\n", bfs(end));
}

猜你喜欢

转载自www.cnblogs.com/booiris/p/10743005.html