HDU1067 Gap( BFS+ HASH 剪枝,矩阵用一个数表示)
2015-08-07 22:25
399 查看
题意:在4*8 的图中,给你4种类型的牌,每种牌序号1-7,比如42表示第4种牌的第二张,现在给你4*7一共28张,同时最左边的一列开始空的,第一步你要做的是把每种类型的1号牌从上到下放在这列空的位置上,然后在新出现的空位置,你要挑选空位子左边的那张牌的后继,如果没有的话,就不能操作。
解法:题目的状态很多,还有要怎么表示一个状态已经搜索过了呢。那就把矩阵做一下转化,把当前矩阵按行展开,以2为基数化为十进制的数(最大2^32,所以用Long Long),接下来存储这些整数,用map,set应该也可以,可能稍微慢点,我这里用简单的hash
解法:题目的状态很多,还有要怎么表示一个状态已经搜索过了呢。那就把矩阵做一下转化,把当前矩阵按行展开,以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; }
相关文章推荐
- cocos2d-x CCScale9Sprite实例
- c#语言与unity3D
- Qt_QJson等的简单应用
- Linux一键web环境搭建攻略
- HDU 5358 First One 数学+尺取法
- 18、C语言和设计模式(建造者模式)
- Android应用:自定义SurfaceView
- MZL's simple problem(STL multiset的应用)
- 544B. Sea and Islands
- PyQt5初级教程--PyQt5中的菜单和工具栏[4/13]
- POJ1154
- 快速排序:数组
- Java 中必须了解的常用类
- .h和.cpp的用法与区别
- window系统查看端口,查找端口,杀死进程
- 进程间的通信如何实现
- hdu5362 Just A String(dp)
- 不等式转不降序列题
- 判断有向图是否有环及拓扑排序
- 《软件随想录》第二部分 第10节 给计算机系学生的建议