【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 }
复制代码

 

posted @   AlphaInf  阅读(262)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
历史上的今天:
2017-10-25 【codeforces 24D】损坏的机器人
点击右上角即可分享
微信分享提示