斯坦纳树模板题,记录一下路径即可
#include <bits/stdc++.h>
using namespace std;
const int dx[4]={0,-1,0,1},dy[4]={-1,0,1,0};
const int N=15;
int n,m,tot,max_statue,l,r,ex,ey;
int c[N][N],ans[N][N],f[N][N][1<<10];
bool vis[N][N];
struct node{int x,y;}q[N*N];
struct number{int x,y,p;}pre[N][N][1<<10];
void spfa(int p)
{
while (l<=r)
{
int x=q[l].x,y=q[l].y;
l++;
vis[x][y]=false;
for (register int i=0; i<4; ++i)
{
int xx=x+dx[i],yy=y+dy[i];
if (xx<1 || xx>n || yy<1 || yy>m) continue;
if (f[xx][yy][p]>f[x][y][p]+c[xx][yy])
{
f[xx][yy][p]=f[x][y][p]+c[xx][yy];
pre[xx][yy][p]=(number){x,y,p};
if (!vis[xx][yy]) r++,q[r]=(node){xx,yy},vis[xx][yy]=true;
}
}
}
}
void dfs(int x,int y,int p)
{
ans[x][y]=1;
if (!pre[x][y][p].p) return;
number now=pre[x][y][p];
if (now.x==x && now.y==y)
{
dfs(now.x,now.y,now.p);
dfs(now.x,now.y,p^now.p);
}
else
{
dfs(now.x,now.y,now.p);
}
}
int main(){
scanf("%d%d",&n,&m);
memset(f,60,sizeof(f));
for (register int i=1; i<=n; ++i)
for (register int j=1; j<=m; ++j)
{
scanf("%d",&c[i][j]);
if (!c[i][j]) f[i][j][1<<tot]=0,tot++,ex=i,ey=j;
}
max_statue=(1<<tot)-1;
for (register int p=1; p<=max_statue; ++p)
{
l=1; r=0;
for (register int i=1; i<=n; ++i)
for (register int j=1; j<=m; ++j)
{
for (register int pp=p; pp; pp=p&(pp-1))
{
if (f[i][j][p]>f[i][j][pp]+f[i][j][p^pp]-c[i][j])
{
f[i][j][p]=f[i][j][pp]+f[i][j][p^pp]-c[i][j],pre[i][j][p]=(number){i,j,pp};
}
}
r++,q[r]=(node){i,j},vis[i][j]=true;
}
spfa(p);
}
dfs(ex,ey,max_statue);
printf("%d\n",f[ex][ey][max_statue]);
for (register int i=1; i<=n; ++i)
{
for (register int j=1; j<=m; ++j)
if (!c[i][j]) putchar('x'); else if (ans[i][j]) putchar('o'); else putchar('_');
putchar('\n');
}
return 0;
}