P4011 孤岛营救问题(压状+bfs最短路)

传送门

题目描述:

给我们一个矩形地图,地图上有一些路径需要特定的钥匙才能走,有些路径不能走,钥匙散落在地图上,

问最少需要多少步能从(1,1)走到(m,n)。

数据范围,1<=m<=n<=10,钥匙数量1<=k<=10;

思路;对每个点压状,用dp[x][y][s]表示走到(x,y)时手里有钥匙集合s的最小步数,而由于路径长度都是1,

所以直接用bfs求解,而且每次到达每个点时,这个点的最小步数就确定了。

但是我没过,我对着题解看了半天也没过,吐了

代码(没过):

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 10000005;
const int inf = 0x3f3f3f3f;
int dx[4] = { -1,1,0,0 };
int dy[4] = { 0,0,1,-1 };
int f[11][11][11][11];
int cnt[11][11];
int key[11][11][11];
bool vis[11][11][2048];
int n, m, p,k,s;
struct point {
    int x, y, cos, len;
};
int bfs(int x, int y) {
    queue<point>q;
    int nows = 0;
    for (int i = 1; i <= cnt[x][y]; i++) {//把起点的钥匙拿上
        nows |= (1<<(key[x][y][i] - 1));
    }
    vis[x][y][nows] = 1;
    q.push({ x,y,nows,0});
    while (!q.empty()) {
        point p = q.front(); q.pop();
        if (p.x == m && p.y == n) {
            return p.len;
        }
        for (int d = 0; d < 4; d++) {
            int tx = p.x + dx[d];
            int ty = p.y + dy[d];
            int pres = p.cos,opt = f[p.x][p.y][tx][ty];
            if (tx<1 || tx>m || ty<1 || ty>n||opt<0||(opt&& !(pres & (1 << (opt - 1)))))continue;
            //超届,不能走,能走但是需要的钥匙没拿到三种情况都不能移动
            //第一次移动到一个位置时,到达那个位置的时间一定是最短的,这也就是我们走到终点直接输出结果的原因
            for (int i = 1; i < cnt[tx][ty]; i++) {//把目的位置的钥匙拿上
                pres |= (1<<(key[tx][ty][i] - 1));
            }
            if (vis[tx][ty][pres])continue;//走过了
            vis[tx][ty][pres] = 1;
            q.push({ tx,ty,pres,p.len + 1 });//进入
        }
    }
    return -1;
}
int main() {
    freopen("test.txt", "r", stdin);
    scanf("%d%d%d%d", &m, &n, &p,&k);
    for (int i = 1; i <= k; i++) {
        int x1, y1, x2, y2, c;
        scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &c);
        if (c)f[x1][y1][x2][y2]=f[x2][y2][x1][y1] = c;//可以走,需要钥匙
        else f[x1][y1][x2][y2]=f[x2][y2][x1][y1] = -1;//不能走
    }
    int num; scanf("%d", &num);
    for (int i = 1; i <= num; i++) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        key[a][b][++cnt[a][b]] = c;//该位置放置有那些钥匙
    }
    printf("%d\n", bfs(1, 1));
    return 0;
}

 

posted @ 2021-04-22 19:28  cono奇犽哒  阅读(90)  评论(0)    收藏  举报