题目大意
解题思路
每层单独考虑,就是平面图的最小生成树,斯坦纳树。设F[i][j][s]表示当前在(i,j)目标点的选取情况为s的最小花费,观察可知当前状态可以由邻近节点走一步得来,也可以由当前节点s的两个子状态得来,注意减去重复的当前点的花费。我们可以枚举s,先更新所有点s的答案,再通过spfa更新其他点的答案。
对于多层,考虑先把下一层解决,把下一层当作一个目标点加在当前层上,每个点都要这样做,这样就可以解决从当前层走到最后的花费,问题就可以解决了。
code
;
Fo(j,1,N)Fo(k,1,M){
F[j][k][0]=A[i][j][k];
Fo(l,1,Mxs)F[j][k][l]=Inf;
F[j][k][1<<(K[i]-1)]=G[j][k]+A[i][j][k];
}
Fo(j,1,K[i]-1)F[B[i][j][0]][B[i][j][1]][1<<(j-1)]=A[i][B[i][j][0]][B[i][j][1]];
//Fo(j,1,K)scanf("%d%d",&B[j][0],&B[j][1]),F[B[j][0]][B[j][1]][1]=F[B[j][0]][B[j][1]][0];
Fo(s,1,Mxs){
int He=0,Ti=0;
for(int ss=s;ss;ss=(ss-1)&s)Fo(j,1,N)Fo(k,1,M)
F[j][k][s]=Min(F[j][k][s],F[j][k][ss]+F[j][k][s-ss]-A[i][j][k]);
//Fo(j,1,K)F[B[j][0]][B[j][1]][s]=F[B[j][0]][B[j][1]][s^(1<<(j-1))];
Fo(j,1,N)Fo(k,1,M)Q[++Ti][0]=j,Q[Ti][1]=k,Inq[j][k]=1;
while(He!=Ti){
int X=Q[++He][0],Y=Q[He][1];
Fo(l,0,3)if(F[X+W[l][0]][Y+W[l][1]][s]>F[X][Y][s]+A[i][X+W[l][0]][Y+W[l][1]]){
F[X+W[l][0]][Y+W[l][1]][s]=F[X][Y][s]+A[i][X+W[l][0]][Y+W[l][1]];
if(!Inq[X+W[l][0]][Y+W[l][1]]){
Inq[X+W[l][0]][Y+W[l][1]]=1;
Q[++Ti][0]=X+W[l][0];
Q[Ti][1]=Y+W[l][1];
if((Q[Ti][0]<1)||(Q[Ti][1]<1)){
int bb;
bb++;
}
}
}
Inq[X][Y]=0;
}
}
Fo(j,1,N)Fo(k,1,M)G[j][k]=F[j][k][Mxs];
}
int Ans=Inf;
Fo(j,1,N)Fo(k,1,M)Ans=Min(Ans,G[j][k]);
printf("%d",Ans);
return 0;
}