【题意】:最基础的斯坦纳树。

【题解】:只需要用spfa dp一次即可,要记录状态的前驱状态保存方案。

【代码】:
  1 #include "iostream"
  2 #include "cstdio"
  3 #include "cstring"
  4 #include "algorithm"
  5 #include "vector"
  6 #include "queue"
  7 #include "cmath"
  8 #include "string"
  9 #include "cctype"
 10 #include "map"
 11 #include "iomanip"
 12 using namespace std;
 13 #define pb push_back
 14 #define mp make_pair
 15 #define fi first
 16 #define se second
 17 #define lc(x) (x << 1)
 18 #define rc(x) (x << 1 | 1)
 19 #define lowbit(x) (x & (-x))
 20 #define ll long long
 21 const int inf = 1 << 29;
 22 int dp[210][1<<7], pre[210][1<<7];
 23 int n, m, k, nn, mm;
 24 int hash[210];
 25 int maz[110][110];
 26 char g[110][110];
 27 bool visit[210][1<<7];
 28 int dx[] = {0, 0, -1, 1};
 29 int dy[] = {-1, 1, 0, 0};
 30 
 31 struct Node {
 32     int u, st;
 33     Node(){}
 34     Node(int _u, int _st) {
 35         u = _u, st = _st;
 36     }
 37 };
 38 queue<Node> que;
 39 
 40 bool check(int x, int y) {
 41     if(x >= 0 && x < n && y >= 0 && y < m) return true;
 42     return false;
 43 }
 44 
 45 void update(int u, int st, int w, int fa) {
 46     if(dp[u][st] > w) {
 47         dp[u][st] = w;
 48         pre[u][st] = fa;
 49         if(!visit[u][st]) {
 50             que.push(Node(u, st));
 51             visit[u][st] = true;
 52         }
 53     }
 54 }
 55 
 56 void dfs(int u, int st) {
 57     int x = u / m, y = u % m;
 58     g[x][y] = 'X';
 59     if(pre[u][st] == -1) return;
 60     else {
 61         int v = pre[u][st] / 1000, stt = pre[u][st] % 1000;
 62         dfs(v, stt);
 63         if(stt - st) dfs(v, st - stt);//牛叉的记录,拆分当前状态
 64     }
 65 }
 66 
 67 void solve() {
 68     while(!que.empty()) {
 69         Node now = que.front();
 70         que.pop();
 71         int u = now.u, x = now.u / m, y = now.u % m, st = now.st;
 72         visit[u][st] = false;
 73         for(int i = 0; i < 4; i++) {
 74             int xx = x + dx[i], yy = y + dy[i];
 75             if(!check(xx, yy)) continue;
 76             int v = xx * m + yy;
 77             update(v, st, dp[u][st] + maz[xx][yy], u * 1000 + st);
 78         }
 79         int t = mm - 1 - st;
 80         for(int i = t; i; i = (i-1) & t) {
 81             update(u, i | st, dp[u][i] + dp[u][st] - maz[x][y], u * 1000 + st);
 82         }
 83     }
 84     int ans = inf, u;
 85     for(int i = 0; i < nn; i++) {
 86         if(ans > dp[i][mm-1]) {
 87             ans = dp[i][mm-1];
 88             u = i;
 89         }
 90     }
 91     dfs(u, mm - 1);
 92     cout << ans << endl;
 93     for(int i = 0; i < n; i++) {
 94         for(int j = 0; j < m; j++)
 95             cout << g[i][j];
 96         cout << endl;
 97     }
 98 }
 99 
100 int main() {
101     while(cin >> n >> m >> k) {
102         while(!que.empty()) que.pop();
103         for(int i = 0; i < n; i++) {
104             for(int j = 0; j < m; j++) {
105                 cin >> maz[i][j];
106                 g[i][j] = '.';
107             }
108         }
109         nn = n * m, mm = 1 << k;
110         memset(hash, 0, sizeof(hash));
111         memset(visit, falsesizeof(visit));
112         for(int i = 0; i < nn; i++) 
113             for(int j = 0; j < mm; j++)
114                 dp[i][j] = inf;
115         for(int i = 0, a, b; i < k; i++) {
116             cin >> a >> b;
117             a--, b--;
118             int u = a * m + b;
119             hash[u] = 1 << i;
120             update(u, hash[u], maz[a][b], -1);
121         }
122         solve();
123     }
124     return 0;
125 }
126