BZOJ 1054 HAOI2008 移动玩具

题目类似于八数码,BFS+判重。

可以直接把16个数字当成二进制Hash。

#include <cstdio>
#include <algorithm>
#include <map>
#include <queue>
#define up(a,b,c) for(int c=a;c<=b;++c)
#define down(a,b,c) for(int c=a;c>=b;--c)
using namespace std;

map<int,bool>vis;

struct node{
    int State[5][5];
    int Code,Step;
}Start,End;

int fx[]={0,0,-1,0,1},fy[]={0,-1,0,1,0};
int Out;

int MakeCode(node a){
    //这里MakeCode是将16个数转化为2进制
    //但是如果第一位是0 那么就无法进行了 0<<1 0<<2都是0啊
    //所以前置增加一位数字1 也就是二进制是17位的
    //不会爆int 因为1<<17最大也是就是13W左右 
    int Code=1;
    up(1,4,i){
        up(1,4,j){
            Code<<=1;
            if(a.State[i][j]) Code|=1;
        }
    }
    return Code;
}

bool Can(int x,int y){
    if(x<1 || y<1 || x>4 || y>4) return false;
    return true;
}

void SWAP(int &a,int &b){
    int c = a;
    a = b;
    b = c;
}

void BFS(){
    if(Start.Code==End.Code) return;
    queue<node>Q;
    Q.push(Start);
    while( !Q.empty() ){
        node now = Q.front();
        now.Step++;
        Q.pop();
        up(1,4,i){
            up(1,4,j){
                if(now.State[i][j]){
                    up(1,4,k){
                        int x = i+fx[k];
                        int y = j+fy[k];
                        if( Can(x,y) ){
                            SWAP(now.State[i][j],now.State[x][y]);
                            int Code = MakeCode(now);
                            if(Code==End.Code){
                                End.Step = now.Step;
                                return;
                            }
                            if(!vis[Code]){
                                vis[Code]=1;
                                Q.push(now);
                            }
                            SWAP(now.State[i][j],now.State[x][y]);
                        }
                    }
                }
            }
        }
    }
}

void init(){
    char s[23];
    up(1,4,i){
        scanf("%s",s+1);
        up(1,4,j){
            Start.State[i][j] = s[j]-'0';
        }
    }
    Start.Step=0;
    int CODE = MakeCode(Start);
//    printf("开始:%d\n",CODE);
    Start.Code=CODE;
    vis[CODE]=1;
    up(1,4,i){
        scanf("%s",s+1);
        up(1,4,j){
            End.State[i][j] = s[j]-'0';
        }
    }
    CODE = MakeCode(End);    
//    printf("结束:%d\n",CODE);
    End.Code=CODE;
    vis[CODE]=1;
}

int main(){
    init();
    BFS();
    printf("%d\n",End.Step);
    return 0;
    
}

 

转载于:https://www.cnblogs.com/OIerLYF/p/7510582.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值