zoukankan      html  css  js  c++  java
  • 【GDOI2015】 推箱子 状态压缩+bfs

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

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

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

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

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

    发现这是一个网格图,且边权都是$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 }
  • 相关阅读:
    [转]面向接口编程详解(二)——编程实例
    [转]面向接口编程详解(一)——思想基础
    [转] LINQ to SQL快速上手 step by step
    Java备份MySQl数据库,并备份图片数据
    用密码密码拦截
    引用 MySQL集群:主从数据库配置 实现查询负载
    Oracle 对表操作 提示:资源正忙,要求指定nowait
    Jquery一款非好的图片轮换效果
    CodeBlocks集成ObjectiveC开发 Windows下学习ObjectiveC
    查询指定库中所有表
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/9852937.html
Copyright © 2011-2022 走看看