码迷,mamicode.com
首页 > 其他好文 > 详细

HDU1067 Gap( BFS+ HASH 剪枝,矩阵用一个数表示)

时间:2015-08-08 00:02:57      阅读:200      评论:0      收藏:0      [点我收藏+]

标签:hdu1067

题意:在4*8 的图中,给你4种类型的牌,每种牌序号1-7,比如42表示第4种牌的第二张,现在给你4*7一共28张,同时最左边的一列开始空的,第一步你要做的是把每种类型的1号牌从上到下放在这列空的位置上,然后在新出现的空位置,你要挑选空位子左边的那张牌的后继,如果没有的话,就不能操作。
解法:题目的状态很多,还有要怎么表示一个状态已经搜索过了呢。那就把矩阵做一下转化,把当前矩阵按行展开,以2为基数化为十进制的数(最大2^32,所以用Long Long),接下来存储这些整数,用map,set应该也可以,可能稍微慢点,我这里用简单的hash

#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<set>
#include<stack>
#define cl(a,b) memset(a,b,sizeof(a));
#define LL long long
#define P pair<int,int>
#define X first
#define Y second
#define pb push_back
#define out(x) cout<<x<<endl;
using namespace std;
const int maxn=25;
const int inf=9999999;
const int mod=100007;

struct node{
    int x[4],y[4];//四个空格的位置
    int a[4][8];//每一步的图的状态
    int step;//步数 
};
int aim[][8]={//目标的状态
{11,12,13,14,15,16,17,0},
{21,22,23,24,25,26,27,0},
{31,32,33,34,35,36,37,0},
{41,42,43,44,45,46,47,0}
};

vector<LL> hash_[mod];//hsah
void insert(LL key){//hash插入函数
    int pos=(key%mod+mod)%mod;
    hash_[pos].pb(key);
}
bool find(LL key){//hash查找函数
    int pos=(key%mod+mod)%mod;
    int N=hash_[pos].size();
    for(int i=0;i<N;i++){
        if(hash_[pos][i]==key)return true;
    }
    return false;
}

LL aimEncode=98430874871LL;///这个数是用encode函数计算aim数组所得到的
LL encode(int x[][8]){///把矩阵按行展开,接着以二为基数,化为十进制数,然后hash下
    LL num=0;
    for(int i=0;i<4;i++){
        for(int j=0;j<8;j++){
            num+=x[i][j]*(1LL<<(i*8+j));
        }
    }
    return num;
}

node st;
int bfs(){
    queue<node> q;
    st.step=0;
    q.push(st);
    insert(encode(st.a));//访问标记

    while(!q.empty()){
        node tt=q.front();q.pop();
        for(int i=0;i<4;i++){//一次扩展四个空格
            node s=tt;
            int x=s.a[s.x[i]][s.y[i]-1];
            if(x%10==7||x==0)continue;
            x++;
            for(int j=0;j<4;j++)for(int k=0;k<8;k++)if(s.a[j][k]==x){
                swap(s.a[j][k],s.a[s.x[i]][s.y[i]]);
                LL tmp=encode(s.a);
                if(tmp==aimEncode){
                    return s.step+1;
                }
                if(!find(tmp)){
                    insert(tmp);
                    s.step++;
                    s.x[i]=j;
                    s.y[i]=k;
                    q.push(s);
                }
                goto A;
            }
            A:;
        }
    }
    return -1;
}


int main(){

    int T;
    scanf("%d",&T);
    while(T--){
        //cl(st.a,0);
        for(int i=0;i<mod;i++)hash_[i].clear();
        st.a[0][0]=st.a[1][0]=0;
        st.a[2][0]=st.a[3][0]=0;
        int num=0;
        for(int i=0;i<4;i++){
            for(int j=1;j<=7;j++){
                int x;
                scanf("%d",&st.a[i][j]);
                x=st.a[i][j];
                if(x==11){
                    swap(st.a[0][0],st.a[i][j]);
                    st.x[num]=i;st.y[num++]=j;
                }
                else if(x==21){
                    swap(st.a[1][0],st.a[i][j]);
                    st.x[num]=i;st.y[num++]=j;
                }
                else if(x==31){
                    swap(st.a[2][0],st.a[i][j]);
                    st.x[num]=i;st.y[num++]=j;
                }
                else if(x==41){
                    swap(st.a[3][0],st.a[i][j]);
                    st.x[num]=i;st.y[num++]=j;
                }
            }
        }///end of for

        if(encode(st.a)==aimEncode){
            puts("0");continue;
        }
        printf("%d\n",bfs());

    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU1067 Gap( BFS+ HASH 剪枝,矩阵用一个数表示)

标签:hdu1067

原文地址:http://blog.csdn.net/u013167299/article/details/47346085

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!