This is the question of the Changsha Invitational competition. At that time, it was a sign-in question.
This type of question is still very common. Let's talk about the ideas.
The first step is to pre-process the distance between each treasure and the distance to the edge. You can directly perform SPFA on each treasure.
Then there is the classic process of TSP.
# Include <set> # include <map> # include <stack> # include <cmath> # include <queue> # include <cstdio> # include <string> # include <vector> # include <iomanip> # include <cstring> # include <iostream> # include <algorithm> # define Max 2505 # define FI first # define SE second # define ll long # define PI acos (-1, 1.0) # define inf 1111111111 # define LL (x) (x <1) # define bug puts ("here") # define PII pair <in T, int> # define RR (x) (x <1 | 1) # define mp (a, B) make_pair (a, B) # define mem (a, B) memset (a, B, sizeof (a) # define infA (a) for (int I = 0; I <= n; ++ I) a [I] = inf; # define REP (I, s, t) for (int I = (s); I <= (t); ++ I) using namespace std; inline void RD (int & ret) {char c; do {c = getchar () ;}while (c <'0' | c> '9 '); ret = c-'0'; while (c = getchar ()> = '0' & c <= '9') ret = ret * 1 0 + (c-'0');} inline void OT (int a) {if (a> = 10) OT (a/10 ); putchar (a % 10 + '0') ;}# define N 222 # define K 15 int Map [N] [N]; struct tru {int x, y ;} tk [K]; int tt; int MM [K] [K]; int dp [1 <K] [K]; int dis [N] [N]; bool vis [N] [N]; PII qe [1111111]; int D [K]; int n, m; int mx [4] = {0, 0, 1, -1}; int my [4] = {1,-1, 0, 0}; int inmap (int x, int y) {if (x> = 0 & x <n & y> = 0 & y <m & Map [x] [y]! =-1) return 1; return 0;} void init (int pos) {for (int I = 0; I <n; I ++) {for (int j = 0; j <m; j ++) {dis [I] [j] = inf; vis [I] [j] = 0 ;}} dis [tk [pos]. x] [tk [pos]. y] = Map [tk [pos]. x] [tk [pos]. y] =-1? Inf: 0; int h = 0, t = 0; qe [h ++] = mp (tk [pos]. x, tk [pos]. y); while (h> t) {PII tp = qe [t ++]; vis [tp. FI] [tp. SE] = 0; if (tp. FI = 0 | tp. FI = n-1 | tp. SE = 0 | tp. SE = m-1) {D [pos] = min (D [pos], dis [tp. FI] [tp. SE]) ;}for (int I = 0; I <4; I ++) {int tx = tp. FI + mx [I]; int ty = tp. SE + my [I]; if (inmap (tx, ty) {if (dis [tx] [ty]> dis [tp. FI] [tp. SE] + Map [tx] [ty]) {di S [tx] [ty] = dis [tp. FI] [tp. SE] + Map [tx] [ty]; if (! Vis [tx] [ty]) {vis [tx] [ty] = 1; qe [h ++] = mp (tx, ty );}}}}}} int main () {# ifndef ONLINE_JUDGE freopen ("in.txt", "r", stdin); freopen ("out.txt", "w", stdout); # endif int T; cin> T; while (T --) {cin> n> m; REP (I, 0, n-1) {REP (j, 0, m-1) scanf ("% d", & Map [I] [j]);} cin> tt; REP (I, 0, tt-1) {RD (tk [I]. x); RD (tk [I]. y);} REP (I, 0, tt-1) {REP (j, 0, tt-1) {MM [I] [j] = inf ;} MM [I] [I] = 0; D [I] = inf ;}for (int I = 0; I <(1 <tt); I ++) {for (int j = 0; j <tt; j ++) dp [I] [j] = inf;} REP (I, 0, tt-1) {init (I); REP (j, 0, tt-1) {if (I = j) continue; MM [I] [j] = min (MM [I] [j], dis [tk [j]. x] [tk [j]. y]); // The closest distance between the treasure and the treasure} dp [1 <I] [I] = D [I] + Map [tk [I]. x] [tk [I]. y]; // The closest distance to the edge of the treasure} for (int I = 0; I <1 <tt; I ++) {for (int j = 0; j <tt; j ++) {if (I & (1 <j) = 0) continue; if (dp [I] [j] = inf) continue; for (int k = 0; k <tt; k ++) {if (I & (1 <k) continue; int tp = I | (1 <k); dp [tp] [k] = min (dp [tp] [k], dp [I] [j] + MM [j] [k]) ;}} int ans = inf; for (int I = 0; I <tt; I ++) {ans = min (ans, dp [(1 <tt)-1] [I] + D [I]);} cout <ans <endl ;} return 0 ;} /* 5 4 4 3 3 3 3 3 3-1-1-1 3-1 3 3 3 3-1-1 1 1 2 2 5 5 1 1 1 1 1 1- 1-1-1-1 1-1-1-1-1 1-1-1-1-1 1-1 1-1-1-1-1-1-1 2 4 0 4 3 3 3 2 3 5 4 3 4 2 1 1 1 3 3 3 3 3 5 4 3 1 2 2 1 2 2 2 */