【jzoj3737】【挖宝藏】【斯坦纳树】【状态压缩动态规划】

来源:互联网 发布:tower windows 破解版 编辑:程序博客网 时间:2024/05/16 08:55

题目大意

这里写图片描述

解题思路

每层单独考虑,就是平面图的最小生成树,斯坦纳树。设F[i][j][s]表示当前在(i,j)目标点的选取情况为s的最小花费,观察可知当前状态可以由邻近节点走一步得来,也可以由当前节点s的两个子状态得来,注意减去重复的当前点的花费。我们可以枚举s,先更新所有点s的答案,再通过spfa更新其他点的答案。

对于多层,考虑先把下一层解决,把下一层当作一个目标点加在当前层上,每个点都要这样做,这样就可以解决从当前层走到最后的花费,问题就可以解决了。

code

#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>#define LF double#define LL long long#define Min(a,b) ((a<b)?a:b)#define Max(a,b) ((a>b)?a:b)#define Fo(i,j,k) for(int i=j;i<=k;i++)#define Fd(i,j,k) for(int i=j;i>=k;i--)using namespace std;int const Mxn=10,Mxa=1<<10,Mxsi=1e4,Inf=1e9;int H,N,M,A[Mxn+9][Mxn+9][Mxn+9],F[Mxn+9][Mxn+9][Mxa+9],    B[Mxn+9][Mxn+9][2],Q[Mxsi+9][2],Inq[Mxn+9][Mxn+9],K[Mxn+9],    W[4][2]={{-1,0},{0,-1},{0,1},{1,0}},G[Mxn+9][Mxn+9];int main(){    //freopen("treasure.in","r",stdin);    //freopen("treasure.out","w ",stdout);    freopen("d.in","r",stdin);    freopen("d.out","w ",stdout);    scanf("%d%d%d",&H,&N,&M);    Fo(i,1,H)Fo(j,1,N)Fo(k,1,M)scanf("%d",&A[i][j][k]);    //Fo(j,1,N)Fo(k,1,M)Fo(l,1,Mxa)F[j][k][l]=Inf;    Fo(i,1,H){        scanf("%d",&K[i]);        Fo(j,1,K[i])scanf("%d%d",&B[i][j][0],&B[i][j][1]);    }    Fd(i,H,1){        K[i]++;int Mxs=(1<<K[i])-1;        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;}
0 0