5 4 ....# ...#. ..... ..... ..... 2 3 1 4 1 2 3 5 2 3 3 1 5 4 2 1
7
题意:有一个图,#表示这个格子无法走到,然后格子之间移动一格花费一分钟,通道之间移动不花费时间,求通
过所有的通道花费的最小时间.
首先bfs预处理每个通道终点到所有点的最短距离,然后用dp[i][j]表示通道经过状态为i下在j通道终点的最少
花费,那么dp[i][j]=min(dp[i^(1<<j)][k]+dis (k,j)).
坑点是不能通过所有通道的情况的判断.
#include <bits/stdc++.h> using namespace std; #define maxn 16 #define maxm 1<<16 #define INF 11111111 int dis[333][333]; int n, m, Max; char mp[maxn][maxn]; int s[maxn][2], t[maxn][2];//起点终点 int dp[maxm][maxn]; int id (int x, int y) { return x*n+y; } bool vis[maxn][maxn]; #define move Move const int move[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; bool legal (int x, int y) { if (x < 0 || y < 0 || x >= n || y >= n) return 0; if (mp[x][y] == '#') return 0; return 1; } void bfs (int x, int y) { queue <int> gg; while (!gg.empty ()) gg.pop(); memset (vis, 0, sizeof vis); gg.push (id (x, y)); vis[x][y] = 1; dis[id(x,y)][id(x,y)] = 0; while (!gg.empty ()) { int now = gg.front (); gg.pop (); int nowx = now/n, nowy = now%n; for (int i = 0; i < 4; i++) { int xx = nowx+move[i][0], yy = nowy+move[i][1]; if (!legal (xx, yy) || vis[xx][yy]) continue; dis[id(x, y)][id (xx, yy)] = dis[id(x, y)][id (nowx, nowy)]+1; vis[xx][yy] = 1; gg.push (id (xx, yy)); } } return ; } vector <int> num[maxn]; #define count Count int count (int num) { int ans = 0; while (num) { if (num&1) ans++; num >>= 1; } return ans; } void init () { for (int i = 0; i <= m; i++) num[i].clear (); for (int i = 0; i < Max; i++) { num[count (i)].push_back (i); } /*for (int i = 0; i <= m; i++) { for (int j = 0; j < num[i].size (); j++) { cout << num[i][j] << " "; } cout << endl; }*/ return ; } int main () { //freopen ("in", "r", stdin); while (scanf ("%d%d", &n, &m) == 2) { memset (dis, -1, sizeof dis); for (int i = 0; i < n; i++) { scanf ("%s", mp[i]); } Max = (1<<m); for (int i = 0; i < m; i++) { scanf ("%d%d%d%d", &s[i][0], &s[i][1], &t[i][0], &t[i][1]); s[i][0]--, s[i][1]--, t[i][0]--, t[i][1]--; bfs (t[i][0], t[i][1]); } for (int i = 0; i < Max; i++) { for (int j = 0; j < m; j++) dp[i][j] = INF; } for (int i = 1, j = 0; i < Max; i <<= 1, j++) { dp[i][j] = 0; } init (); for (int cnt = 2; cnt <= m; cnt++) { for (int l = 0; l < num[cnt].size (); l++) { int i = num[cnt][l]; for (int j = 0; j < m; j++) if (i&(1<<j)) { for (int k = 0; k < m; k++) if ((1<<k)&(i^(1<<j))) { if (dis[id(t[k][0],t[k][1])][id(s[j][0],s[j][1])] == -1) continue; dp[i][j] = min (dp[i][j], dp[i^(1<<j)][k]+dis[id(t[k][0],t[k][1])][id(s[j][0],s[j][1])]); } } } } int ans = INF; for (int i = 0; i < m; i++) { ans = min (ans, dp[Max-1][i]); } if (ans >= INF) printf ("-1\n"); else printf ("%d\n", ans); } return 0; }