题目
Description
Input
Sample Input
2 2 2
10 9
10 10
10 1
10 10
1 1 1
1 2 2
Output
输出一个整数,为矿工获得所有宝藏的最小代价。
Sample Output
30
Data Constraint
题解
首先这题h等于1的情况即WC2008游览计划,是有后效性的dp,我们考虑状压+spfa松弛解决
然后这题多了一个层数,我们在把上一层传到下一层时可以考虑在下一层新增一个虚拟的宝藏,这个宝藏可以在任意一个点,然后它代表了上面一层全部宝藏都已经选完了,选完之后选择在这个点走下来
具体的实现就是
f[i][j][s]=f[i][j][s′]+f[i][j][s−s′]−a[t][i][j]
其中t表示当前在第t层,并且有s’ and s=s
这就表示了s状态可以由上述两个状态转移而来,而(i,j)点因为走了两次所以减去一次
可以证明这样转移的正确性以及全面性
然后我们对f[x][y][s]做一次spfa松弛就可以了
贴代码
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<math.h>
using namespace std;
const int maxn=13;
int f[maxn][maxn][1<<maxn],ff[maxn][maxn][1<<maxn],a[maxn][maxn][maxn];
int t[maxn][maxn][3];
int h[maxn*maxn*30][3];
int g[maxn];
int go[5][3];
bool bz[maxn][maxn];
int i,j,k,l,hh,m,n,x,y,z,c1,c2,c3,p1,p2,p3,ans,tt,tsm;
void spfa(){
int i,j,k,x1,y1;
i=tt;
j=0;
while (i>j){
j++;
x=h[j][1]; y=h[j][2];
if (bz[x][y]==true) continue;
bz[x][y]=true;
for (k=1;k<=4;k++){
x1=h[j][1]+go[k][1];
y1=h[j][2]+go[k][2];
if (x1==0||y1==0||x1>n||y1>m) continue;
if (f[x][y][c2]+a[c1][x1][y1]<f[x1][y1][c2]){
f[x1][y1][c2]=f[x][y][c2]+a[c1][x1][y1];
bz[x1][y1]=false;
i++;
h[i][1]=x1; h[i][2]=y1;
}
}
}
}
int main(){
freopen("treasure.in","r",stdin);
freopen("treasure.out","w",stdout);
//freopen("t2.in","r",stdin);
scanf("%d%d%d",&hh,&n,&m);
for (i=1;i<=hh;i++){
for (j=1;j<=n;j++){
for (k=1;k<=m;k++) scanf("%d",&a[i][j][k]);
}
}
go[1][1]=go[2][1]=0;
go[3][2]=go[4][2]=0;
go[1][2]=go[3][1]=1;
go[2][2]=go[4][1]=-1;
for (i=1;i<=hh;i++){
scanf("%d",&g[i]);
for (j=1;j<=g[i];j++) scanf("%d%d",&t[i][j][1],&t[i][j][2]);
}
memset(f,127,sizeof(f));
memset(ff,127,sizeof(ff));
tsm=f[1][1][1];
for (p1=1;p1<=n;p1++){
for (p2=1;p2<=m;p2++){
f[p1][p2][0]=0;
}
}
for (i=1;i<=g[1];i++) f[t[1][i][1]][t[1][i][2]][1<<(i-1)]=a[1][t[1][i][1]][t[1][i][2]];
ans=0x7fffffff;
for (c1=1;c1<=hh;c1++){
for (c2=1;c2<=(1<<g[c1])-1;c2++){
tt=0;
memset(bz,false,sizeof(bz));
for (p1=1;p1<=n;p1++){
for (p2=1;p2<=m;p2++){
p3=c2;
while (p3){
p3=(p3-1)&c2;
if (!p3) break;
f[p1][p2][c2]=min(f[p1][p2][c2],f[p1][p2][p3]+f[p1][p2][c2-p3]-a[c1][p1][p2]);
}
if (f[p1][p2][c2]<tsm){
tt++;
h[tt][1]=p1;
h[tt][2]=p2;
if (c1==hh & c2==(1<<g[c1])-1)
ans=min(ans,f[p1][p2][c2]);
}
}
}
spfa();
}
c2=(1<<g[c1])-1;
for (p1=1;p1<=n;p1++){
for (p2=1;p2<=m;p2++){
ff[p1][p2][1<<g[c1+1]]=f[p1][p2][c2]+a[c1+1][p1][p2];
}
}
g[c1+1]++;
for (c2=1;c2<=(1<<g[c1+1])-1;c2++){
for (p1=1;p1<=n;p1++){
for (p2=1;p2<=m;p2++){
f[p1][p2][c2]=ff[p1][p2][c2];
}
}
}
memset(ff,127,sizeof(ff));
for (c2=1;c2<=g[c1+1]-1;c2++){
f[t[c1+1][c2][1]][t[c1+1][c2][2]][1<<(c2-1)]=a[c1+1][t[c1+1][c2][1]][t[c1+1][c2][2]];
}
}
printf("%d",ans);
}