• 【BZOJ 1054】 [HAOI2008]移动玩具


    Description

    在一个4*4的方框内摆放了若干个相同的玩具,某人想将这些玩具重新摆放成为他心中理想的状态,规定移动时只能将玩具向上下左右四个方向移动,并且移动的位置不能有玩具,请你用最少的移动次数将初始的玩具状态移动到某人心中的目标状态。

    Input

    前4行表示玩具的初始状态,每行4个数字1或0,1表示方格中放置了玩具,0表示没有放置玩具。接着是一个空行。接下来4行表示玩具的目标状态,每行4个数字1或0,意义同上。

    Output

    一个整数,所需要的最少移动次数。

    Sample Input

    1111
    0000
    1110
    0010

    1010
    0101
    1010
    0101

    Sample Output

    4
     
    这个题貌似在哪见过,然后找不到了
    其实也不需要见过,双向BFS就够了,就是我的搜索代码太丑
     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 int map[4][4],mb[4][4],b[4][4],bs[2][140000],q[2][140000],h[2],t[2],ans;
     5 bool pd[2][140000],flag;
     6 int hash(int b[4][4]){
     7     int mid=0;
     8     for (int i=0;i<4;i++)
     9         for (int j=0;j<4;j++){
    10             mid=mid<<1;
    11             mid=mid|b[i][j];
    12         }
    13     return mid;
    14 }
    15  
    16 void make(int v,int b[4][4],int f){
    17     int mid=hash(b);
    18     if (!pd[v][mid]) {
    19         pd[v][mid]++;
    20         bs[v][mid]=f+1;
    21         q[v][++t[v]]=mid;
    22     }
    23     if(pd[v^1][mid]) {
    24         flag=1;ans=bs[v][mid]+bs[v^1][mid];//这个地方不需要-1
    25         return;
    26     }
    27 }
    28  
    29 void bfs(int v){
    30     memset(b,0,sizeof(b));
    31     int now=q[v][++h[v]],w=bs[v][now];
    32     int x=3,y=3;
    33     for (int i=1;i<=16;i++){
    34         b[x][y]=now&1;
    35         now=now>>1;
    36         y--; if(y==-1)y=3,x--;
    37     }
    38     for (int i=0;i<=3;i++)
    39         for (int j=0;j<4;j++){
    40             if (i!=0&&b[i-1][j]!=b[i][j]) {
    41                 b[i][j]^=1;b[i-1][j]^=1;
    42                 make(v,b,w);
    43                 if (flag) return;
    44                 b[i][j]^=1;b[i-1][j]^=1;
    45             }
    46             if (i!=3&&b[i+1][j]!=b[i][j]){
    47                 b[i][j]^=1;b[i+1][j]^=1;
    48                 make(v,b,w);
    49                 if (flag) return;
    50                 b[i][j]^=1;b[i+1][j]^=1;
    51             }
    52             if (j!=0&&b[i][j]!=b[i][j-1]){
    53                 b[i][j]^=1;b[i][j-1]^=1;
    54                 make(v,b,w);
    55                 if (flag) return;
    56                 b[i][j]^=1;b[i][j-1]^=1;
    57             }
    58             if (j!=3&&b[i][j]!=b[i][j+1]){
    59                 b[i][j]^=1;b[i][j+1]^=1;
    60                 make(v,b,w);
    61                 if (flag) return;
    62                 b[i][j]^=1;b[i][j+1]^=1;
    63             }
    64         }
    65 }
    66  
    67 int main(){
    68     char s[20];
    69     for (int i=0;i<4;i++){
    70         scanf("%s",s);
    71         for (int j=0;j<4;j++)
    72         map[i][j]=s[j]-'0';
    73     }
    74     for (int i=0;i<4;i++){
    75         scanf("%s",s);
    76         for (int j=0;j<4;j++)
    77         mb[i][j]=s[j]-'0';
    78     }
    79     h[0]=h[1]=0;
    80     make(0,map,-1);make(1,mb,-1);
    81     while(h[0]<t[0]||h[1]<t[1]){
    82         if (h[1]==t[1]) bfs(0);
    83         if (flag) break;
    84         if (h[0]==t[0]) bfs(1);
    85         if (flag) break;
    86         if (t[1]-h[1]<t[0]-h[0]) bfs(1);else bfs(0);
    87         if (flag) break;
    88     }
    89     printf("%d",ans);
    90 }
  • 相关阅读:
    PHP面试系列之Linux(一) ----- Linux基础
    Redis入门(一)---安装
    获取主机ip地址
    Ubuntu安装Apache
    Ubuntu安装MySQL/MariaDB
    Ubuntu安装PHP7
    shell一次性执行多条命令
    将宿主主机上的目录挂载到Docker中
    bind 仿造 重写bind
    echars 饼状图 轮循 水平翻转
  • 原文地址:https://www.cnblogs.com/wuminyan/p/5191631.html
Copyright © 2020-2023  润新知