水题,数据范围提示得太明显了吧,不用动脑子都能知道是状压。
不过还是有坑(当然更可能是我脑子有坑)
f[i][j][k][l]表示当前是第i秒,萃香在(j,k),已经抱到的西瓜状态是l的最少移动次数,然后用BFS一样的办法暴力转移就行,复杂度完全过得去。
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<cctype> #define maxp 7 #define maxt 105 #define maxn 12 using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } int f[maxt][maxp][maxp][1<<maxn]; int q[maxt][maxp][maxp]; int tot; int ux[5]={0,1,0,-1,0}; int wy[5]={0,0,1,0,-1}; int main(){ int h=read(),w=read(),t=read(),sx=read(),sy=read(),n=read(),m=read(); int lim=1<<m; memset(f,127/3,sizeof(f)); int inf=f[0][0][0][0]; f[1][sx][sy][0]=0; for(int i=1;i<=n;++i){ int t1=read(),t2=read(),opt=read(); int to=t2; if(t2>t) t2=t; if(opt==1){ tot++; for(int j=t1;j<to;++j){ int x=read(),y=read(); q[j][x][y]=tot; } } else{ for(int j=t1;j<to;++j){ int x=read(),y=read(); q[j][x][y]=-1; } } } for(int tme=1;tme<=t;++tme){ for(int i=1;i<=h;++i) for(int j=1;j<=w;++j) for(register int k=0;k<lim;++k){ if(f[tme][i][j][k]==inf) continue; for(int l=1;l<=4;++l){ int x=i+ux[l],y=j+wy[l]; if(x==0||y==0||x>h||y>w||q[tme+1][x][y]==-1) continue; int ret=q[tme+1][x][y],now=0; if(ret) now=1<<(ret-1); f[tme+1][x][y][k|now]=min(f[tme+1][x][y][k|now],f[tme][i][j][k]+1); } if(q[tme+1][i][j]!=-1){ int ret=q[tme+1][i][j],now=0; if(ret) now=1<<(ret-1); f[tme+1][i][j][k|now]=min(f[tme+1][i][j][k|now],f[tme][i][j][k]); } } } int ans=inf; for(int i=1;i<=h;++i) for(int j=1;j<=w;++j) if(ans>f[t][i][j][lim-1]) ans=f[t][i][j][lim-1]; if(ans==inf) ans=-1; printf("%d",ans); }