# 【BZOJ 2595】【WC 2008】游览计划

http://www.lydsy.com/JudgeOnline/problem.php?id=2595

#include<cstdio>
#include<cstring>
#include<algorithm>
#define mk(x, y, z) ((x) + (y) * 100 + (z) * 10000)
using namespace std;

int a[13][13], f[13][13][1 << 10], pre[13][13][1 << 10], n, m, q[1000003], head, tail, inf, tot = 0, ans = 0x7fffffff;
bool inq[10003], mark[13][13];

const int dx[4] = {0, -1, 0, 1};
const int dy[4] = {1, 0, -1, 0};

void spfa(int s) {
int u, x, y, tx, ty, t;
while (head != tail) {
u = q[head]; inq[u] = false;
x = u % 100; y = u / 100;
for (int i = 0; i < 4; ++i) {
tx = x + dx[i]; ty = y + dy[i];
if (tx < 1 || tx > n || ty < 1 || ty > m) continue;

t = f[x][y][s] + a[tx][ty];
if (t < f[tx][ty][s]) {
f[tx][ty][s] = t;
pre[tx][ty][s] = mk(x, y, s);
u = mk(tx, ty, 0);
if (!inq[u]) {
inq[u] = true;
++tail; if (tail == 1000003) tail = 0;
q[tail] = u;
}
}
}
}
}

void dfs(int x, int y, int s) {
mark[x][y] = true;
int num = pre[x][y][s]; if (num == 0) return;
if (num / 10000 == s)
dfs(num % 100, num / 100 % 100, s);
else {
dfs(x, y, num / 10000);
dfs(x, y, s ^ (num / 10000));
}
}

void ouit(int totnum) {
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
if (f[i][j][totnum] == ans) {
dfs(i, j, totnum);
return;
}
}

int main() {
scanf("%d%d", &n, &m);
memset(f, 60, sizeof(f)); inf = f[0][0][0];
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j) {
scanf("%d", &a[i][j]);
if (!a[i][j]) {
f[i][j][1 << tot] = 0;
++tot;
}
}

int totnum = (1 << tot) - 1, now;
for (int s = 1; s <= totnum; ++s) {
head = tail = 0;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j) {
for (int t = s & (s - 1); t; t = s & (t - 1)) {
now = f[i][j][t] + f[i][j][s ^ t] - a[i][j];
if (now < f[i][j][s]) {
f[i][j][s] = now;
pre[i][j][s] = mk(i, j, t);
}
}
if (f[i][j][s] != inf)
inq[q[++tail] = mk(i, j, 0)] = true;
}
spfa(s);
}

for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
ans = min(ans, f[i][j][totnum]);
printf("%d\n", ans);

ouit(totnum);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j)
if (mark[i][j])	putchar(a[i][j] ? 'o' : 'x');
else putchar('_');
puts("");
}
return 0;
}

posted @ 2016-12-15 21:02  abclzr  阅读(213)  评论(0编辑  收藏  举报