1. 程式人生 > >計蒜客 藏寶圖

計蒜客 藏寶圖

log clu max 最短 queue tdi nat UC emp

題目鏈接:藏寶圖

說兩種解法。

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; }

如有不當之處歡迎指出!

計蒜客 藏寶圖