计蒜客 藏宝图

题目链接:藏宝图

说两种解法。

1.由于十个点都要走一次,所以可以枚举10个藏宝点的全排列,再把起点$(0,0)$和终点$(0,0)$放在排列的首尾,用11次bfs即可获得一种走法的最短路径。

2.把用二进制来表示每个藏宝点,$(x,y,status)$表示获得了status的宝物,来到了点$(x,y)$

贴出位压代码:

#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 10 + 5;
int mp[maxn][maxn];
int vis[maxn][maxn][(1<<10) + 10];

const int dx[] = {0,0,-1,1};
const int dy[] = {-1,1,0,0};

typedef struct Coordinate {
    int x, y;
    int step;
    int status;
    Coordinate(){}
    Coordinate(int x, int y, int step, int status) {
        this->x = x;
        this->y = y;
        this->step = step;
        this->status = status;
    }
}coor;

int bfs() {
    memset(vis, 0, sizeof(vis));
    queue<Coordinate> Q;
    Q.push(coor(0,0,0,0));
    vis[0][0][0] = 1;
    int goal = (1<<10) - 1;
    while(!Q.empty()) {
        coor a = Q.front(); Q.pop();
        if(a.x == 0 && a.y == 0 && a.status == goal) {
            return a.step;
        }
        for(int i = 0; i < 4; i++) {
            int x = a.x + dx[i];
            int y = a.y + dy[i];
            if(x < 0 || y < 0 || x >= 10 || y >= 10) continue;
            if(mp[x][y] == -1) continue;
            int status;
            if(mp[x][y] > 0) {
                status = a.status | (1 << (mp[x][y] - 1));
            } else {
                status = a.status;
            }
            if(!vis[x][y][status]) {
                vis[x][y][status] = 1;
                coor b = coor(x, y, a.step+1, status);
                Q.push(b);
            }
        }
    }
    return -1;
}

int main() {
    freopen("data.in", "r", stdin);
    for(int i = 0; i < 10; i++) {
        for(int j = 0; j < 10; j++) {
            scanf("%d", &mp[i][j]);
            printf("%4d ", mp[i][j]);
        }
        printf("\n");
    }
    int step = bfs();
    printf("%d\n", step);
    return 0;
}

如有不当之处欢迎指出!

posted @ 2018-03-27 17:10  flyawayl  阅读(338)  评论(0编辑  收藏  举报