【GDOI2015】 推箱子 状态压缩+bfs

请注意$8$是一个美妙的数字

考虑到$8\times 8=64$,而一个unsigned long long是$64$位的,所以考虑用一个$01$状态存储箱子。考虑到箱子能转动,那么四种情况都存一下就可以了。

为了能够快速判断某个位置是否可以放下箱子,我们令$f[i][j]$表示左上角为$(i,j)$,大小为$m\times m$的矩形内的$01$状态。

若箱子可以呆在左上角为$(i,j)$的矩形里,那么箱子的状态值$\&f[i][j]$必然为$0$。

令$dis[i][j][k]$表示箱子当前跑到$(i,j)$,逆时针转动的角度为$k\times90$度的最少步数。

发现这是一个网格图,且边权都是$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 }

猜你喜欢

转载自www.cnblogs.com/xiefengze1/p/9852937.html