題目大意:
n*m的矩陣,矩陣上有k個景點,對於某個不是景點的點,打通它需要耗費(打通後經過不需要耗費),問將n個景點連通需要的最小花費,以及打通的一種最優方案。
分析:
好像是斯坦納樹的模板題,
設表示已經連通的景點狀態爲,這個連通塊包含點時的最小點權和是多少
然後我們從小到大枚舉狀態,
然後先枚舉的一個子集
看前面的狀態能否更新當前的狀態,
然後我們對於能被更新的,
我們去跑最短路,看能否更新其他的
最後得到的最小的即爲最小花費,是景點全部連通時的狀態
然後對於一個方案數,
我們就可以在做狀壓揹包和最短路的時候,
一旦有狀態被更新,我們就存它是怎麼被更新的,
即這個狀態由什麼轉移過來
最後我們對於一個的點我們把它所涉及的點除景點外全部更改成被打通點,dfs即可
代碼:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <vector>
#include <cstring>
#include <algorithm>
#define rep(i, st, ed) for (int i = st; i <= ed; i++)
#define rwp(i, ed, st) for (int i = ed; i >= st; i--)
#define inf 0x3f3f3f3f
#define N 12
using namespace std;
const int dx[] = {-1, 0, 1, 0};
const int dy[] = {0, 1, 0, -1};
int os[N][N][1<<N][2], cs[N][N][1<<N][2], dp[N][N][1<<N], fro[N][N][1<<N], a[N][N], C[N][2], num, n, m, tot;
char ans[N][N];
bool vis[N][N];
queue <int> Q1, Q2;
int cde(int x) {
return (1 << x);
}
bool check(int x, int y) {
if (x < 1 || x > n || y < 1 || y > m) return 0;
return 1;
}
void dfs(int x, int y, int s) {
if (ans[x][y] != 'x') ans[x][y] = 'o';
if (fro[x][y][s] == 1) {
dfs(os[x][y][s][0], os[x][y][s][1], s);
} if (fro[x][y][s] == 2) {
dfs(x, y, cs[x][y][s][0]);
dfs(x, y, cs[x][y][s][1]);
}
}
int main() {
scanf("%d %d", &n, &m);
rep(i, 1, n)
rep(j, 1, m) {
scanf("%d", &a[i][j]);
if (!a[i][j]) C[++num][0] = i, C[num][1] = j;
}
++num;
rep(i, 1, n)
rep(j, 1, m) {
dp[i][j][1] = inf;
if (a[i][j]) dp[i][j][1] = a[i][j];
rep(s, 2, cde(num) - 1) dp[i][j][s] = inf;
}
rep(i, 1, num - 1) dp[C[i][0]][C[i][1]][cde(i)] = 0;
rep(s, 1, cde(num) - 1) {
rep(i, 1, n)
rep(j, 1, m) {
rep(t, 1, s - 1)
if ((s & t) == t)
if (dp[i][j][s] > dp[i][j][t] + dp[i][j][s ^ t] - a[i][j]) {
dp[i][j][s] = dp[i][j][t] + dp[i][j][s ^ t] - a[i][j];
fro[i][j][s] = 2;
cs[i][j][s][0] = t;
cs[i][j][s][1] = s ^ t;
}
if (dp[i][j][s] != inf) Q1.push(i), Q2.push(j), vis[i][j] = 1;
}
while (!Q1.empty()) {
int ux = Q1.front(); Q1.pop();
int uy = Q2.front(); Q2.pop();
rep(c, 0, 3) {
int vx = ux + dx[c];
int vy = uy + dy[c];
if (check(vx, vy) && dp[vx][vy][s] > dp[ux][uy][s] + a[vx][vy]) {
dp[vx][vy][s] = dp[ux][uy][s] + a[vx][vy];
fro[vx][vy][s] = 1;
os[vx][vy][s][0] = ux;
os[vx][vy][s][1] = uy;
if (!vis[vx][vy]) Q1.push(vx), Q2.push(vy), vis[vx][vy] = 1;
}
}
vis[ux][uy] = 0;
}
}
int cdp = 0x7fffffff, asx, asy;
rep(i, 1, n)
rep(j, 1, m) if (cdp > dp[i][j][cde(num) - 1]) { cdp = dp[i][j][cde(num) - 1]; asx = i; asy = j; }
rep(i, 1, n)
rep(j, 1, m) ans[i][j] = (a[i][j] == 0 ? 'x' : '_');
dfs(asx, asy, cde(num) - 1);
printf("%d\n", cdp);
rep(i, 1, n) {
rep(j, 1, m) printf("%c", ans[i][j]); printf("\n");
}
return 0;
}