题目链接:藏宝图
说两种解法。
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(" "); } int step = bfs(); printf("%d ", step); return 0; }
如有不当之处欢迎指出!