【GDOI2015】 推箱子 状态压缩+bfs
请注意8是一个美妙的数字
考虑到8×8=64,而一个unsigned long long是64位的,所以考虑用一个01状态存储箱子。考虑到箱子能转动,那么四种情况都存一下就可以了。
为了能够快速判断某个位置是否可以放下箱子,我们令f[i][j]表示左上角为(i,j),大小为m×m的矩形内的01状态。
若箱子可以呆在左上角为(i,j)的矩形里,那么箱子的状态值&f[i][j]必然为0。
令dis[i][j][k]表示箱子当前跑到(i,j),逆时针转动的角度为k×90度的最少步数。
发现这是一个网格图,且边权都是1,直接随便转移一下就好了。
时间复杂度:O(4n^2+n^2m)。 但是下方的代码是O(4n^2+n^2m^2)的,似乎问题不大。
1 #include<bits/stdc++.h> 2 #define M 2005 3 #define L unsigned long long 4 using namespace std; 5 int INF; 6 char c[100]={0},ch[M][M]={0}; 7 int n,m,box[8][8]={0},Box[8][9]={0},dis[M][M][4]={0}; 8 L b[4]={0},a[M][M]={0}; 9 10 void rotate(){ 11 for(int i=0;i<m;i++) 12 for(int j=0;j<m;j++) 13 Box[m-j-1][i]=box[i][j]; 14 for(int i=0;i<m;i++) 15 for(int j=0;j<m;j++) 16 box[i][j]=Box[i][j]; 17 } 18 L gethash(){ 19 L ans=0; 20 for(int i=0;i<m;i++) 21 for(int j=0;j<m;j++) 22 ans=ans<<1|box[i][j]; 23 return ans; 24 } 25 L gethash(int x,int y){ 26 L ans=0; 27 for(int i=0;i<m;i++) 28 for(int j=0;j<m;j++) 29 ans=ans<<1|(ch[i+x][j+y]=='1'); 30 return ans; 31 } 32 33 int wx[]={0,0,1,-1}; 34 int wy[]={1,-1,0,0}; 35 queue<int> qx,qy,qz; 36 void solve(){ 37 memset(dis,60,sizeof(dis)); 38 INF=dis[0][0][0]; 39 dis[0][0][0]=0; 40 qx.push(0); qy.push(0); qz.push(0); 41 while(!qx.empty()){ 42 int x=qx.front(); qx.pop(); 43 int y=qy.front(); qy.pop(); 44 int z=qz.front(),Z; qz.pop(); 45 46 Z=(z+1)&3; 47 if(dis[x][y][z]+1<dis[x][y][Z]&&((b[Z]&a[x][y])==0)){ 48 qx.push(x); qy.push(y); qz.push(Z); 49 dis[x][y][Z]=dis[x][y][z]+1; 50 } 51 52 Z=(z-1)&3; 53 if(dis[x][y][z]+1<dis[x][y][Z]&&((b[Z]&a[x][y])==0)){ 54 qx.push(x); qy.push(y); qz.push(Z); 55 dis[x][y][Z]=dis[x][y][z]+1; 56 } 57 58 for(int i=0;i<4;i++){ 59 int X=x+wx[i],Y=y+wy[i]; 60 if(X<0||Y<0||X>n-m||Y>n-m) continue; 61 if(dis[x][y][z]+1<dis[X][Y][z]&&(b[z]&a[X][Y])==0){ 62 dis[X][Y][z]=dis[x][y][z]+1; 63 qx.push(X); qy.push(Y); qz.push(z); 64 } 65 } 66 } 67 } 68 69 int main(){ 70 scanf("%d%d",&n,&m); 71 for(int i=0;i<m;i++){ 72 scanf("%s",c); 73 for(int j=0;j<m;j++) 74 box[i][j]=c[j]-'0'; 75 } 76 for(int i=0;i<4;i++){ 77 b[i]=gethash(); 78 rotate(); 79 } 80 81 for(int i=0;i<n;i++) 82 scanf("%s",ch[i]); 83 for(int i=0;i<=n-m;i++) 84 for(int j=0;j<=n-m;j++) 85 a[i][j]=gethash(i,j); 86 87 solve(); 88 89 int minn=INF; 90 for(int i=0;i<4;i++) 91 minn=min(minn,dis[n-m][n-m][i]); 92 if(minn==INF) cout<<-1<<endl; 93 else cout<<minn<<endl; 94 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
2017-10-25 【codeforces 24D】损坏的机器人