斯坦纳树:
主要是DP思想,转化成联通图求最短联通K个点的路径后,可以状态压缩,DP转移分2步,一步本节点合并,一步最短路松弛。另外可以输出路径,注意回溯时\(dp[i][j][s]\)可以由\(dp[i][j][t]和dp[i][j][s-t]\)转移,需要判断一下
#include<bits/stdc++.h>
using namespace std;
#define _f(i,a,b) for(register int i=a;i<=b;++i)
#define f_(i,a,b) for(register int i=a;i>=b;--i)
#define chu printf
#define ll long long
#define ull unsigned long long
inline ll re()
{
ll x=0,h=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')h=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*h;
}
const int N=1e5+100;
int n,m;
int a[12][12],dp[12][12][(1<<10)+100];
int cnt;
struct Node
{
int x,y,s;int dap;
Node(){}
Node(int xx,int yy,int ss,int ddpp)
{
x=xx;y=yy;s=ss;dap=ddpp;
}
Node(int xx,int yy,int ss)
{
x=xx;y=yy;s=ss;
}
bool operator<(const Node&A)const
{
return dap>A.dap;//让小的先来
}
};
priority_queue<Node >q;//点对
Node last[12][12][(1<<10)+100];
int xd[5]={0,1,0,-1};
int yd[5]={1,0,-1,0};
int tpx,tpy,vis[11][11],ans[11][11];
//ans记录装什么,ans(i,j)=1代表是景点,ans(i,j)=2代表要有志愿者
inline void Dij(int s)
{
memset(vis,0,sizeof(vis));
while(!q.empty())
{
Node ls=q.top();q.pop();
if(vis[ls.x][ls.y])continue;
vis[ls.x][ls.y]=1;
// chu("%d %d\n",ls.x,ls.y);
Node nw;
_f(i,0,3)
{
nw.x=ls.x+xd[i];
nw.y=ls.y+yd[i];
if(nw.x>n||nw.y>m||nw.x==0||nw.y==0)continue;
nw.dap=ls.dap+a[nw.x][nw.y];
if(nw.dap<dp[nw.x][nw.y][s])
{
dp[nw.x][nw.y][s]=nw.dap;
last[nw.x][nw.y][s]=Node(ls.x,ls.y,s);
q.push(nw);
}
}
}
}
inline void getans(int x,int y,int s)
{
if(last[x][y][s].s==0)return;
Node ls=last[x][y][s];
// chu("go last:%d %d\n",ls.x,ls.y);
if(a[ls.x][ls.y])
{
ans[ls.x][ls.y]=1;
// chu("mark:%d %d\n",ls.x,ls.y);
}
getans(ls.x,ls.y,ls.s);
if(ls.x==x&&ls.y==y)getans(x,y,s-ls.s);
}
int main()
{
n=re(),m=re();
memset(dp,0x3f,sizeof(dp));
_f(i,1,n)
_f(j,1,m)
{
a[i][j]=re();
if(!a[i][j])++cnt,dp[i][j][1<<(cnt-1)]=0,tpx=i,tpy=j;
}
_f(s,0,(1<<cnt)-1)
{
//chu("out\n");
_f(i,1,n)
_f(j,1,m)
{
for(int k=s&(s-1);k;k=((k-1)&(s)))
{
//chu("jwo\n");
if(dp[i][j][s]>dp[i][j][k]+dp[i][j][s-k]-a[i][j])//如果是景点也一样,不能算2次
dp[i][j][s]=dp[i][j][k]+dp[i][j][s-k]-a[i][j],
last[i][j][s]=Node(i,j,k);
}
if(dp[i][j][s]<0x3f3f3f3f)q.push(Node(i,j,s,dp[i][j][s]));
}
Dij(s);
// chu("s:%d\n",s);
}
chu("%d\n",dp[tpx][tpy][(1<<cnt)-1]);
getans(tpx,tpy,(1<<cnt)-1);
_f(i,1,n)
{
_f(j,1,m)
{
if(!a[i][j])chu("x");
else if(ans[i][j])chu("o");
else chu("_");
}
chu("\n");
}
return 0;
}
/*
4 4
0 1 1 0
2 5 5 1
1 5 5 1
0 1 1 0
*/