【题意】:最基础的斯坦纳树。
【题解】:只需要用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, false, sizeof(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