https://codeforces.com/contest/1517/problem/D
过了一万个人我还是不会
f[i][j][k]表示从i,j走k步的最小距离,然后根据根节点转移就行了,最后就从f[k/2]*2就行了,就相当于来回走一遍
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=510;
const ll inf=1ll<<60;
int n,m,k,cnt,tot,cas;
ll dis[22][maxl*maxl],ans[maxl*maxl];
int num[maxl][maxl];
struct ed{int v,l;};
vector<ed> e[maxl*maxl];
inline void prework()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
num[i][j]=++tot;
for(int i=1;i<=n;i++)
{
for(int j=1;j<m;j++)
{
int l;scanf("%d",&l);
int u=num[i][j],v=num[i][j+1];
e[u].push_back(ed{v,l});
e[v].push_back(ed{u,l});
}
}
for(int i=1;i<n;i++)
for(int j=1;j<=m;j++)
{
int l;scanf("%d",&l);
int u=num[i][j],v=num[i+1][j];
e[u].push_back(ed{v,l});
e[v].push_back(ed{u,l});
}
}
inline void mainwork()
{
if(k&1)
{
for(int i=1;i<=tot;i++) ans[i]=-1;
return;
}
memset(dis,0x3f,sizeof(dis));
for(int i=1;i<=tot;i++) dis[0][i]=0;
for(int i=1;i<=k/2;i++)
for(int u=1;u<=tot;u++)
for(ed ee:e[u])
{
int v=ee.v;
if(dis[i][u]>dis[i-1][v]+ee.l)
dis[i][u]=dis[i-1][v]+ee.l;
}
for(int i=1;i<=tot;i++) ans[i]=dis[k/2][i]*2;
}
inline void print()
{
for(int i=1;i<=tot;i++)
printf("%lld%c",ans[i]," \n"[i%m==0]);
}
int main()
{
int t=1;
//scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}