hdu 1067(hash+bfs)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1067

思路:学会了手写Hash。。。orz....纪念一下。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<queue>
  6 using namespace std;
  7 #define MAXN 1000007
  8 typedef long long ll;
  9 ll Hash[MAXN];
 10 
 11 struct Node{
 12     int map[4][8],step;
 13     bool operator == (const Node &p) const {
 14         for(int i=0;i<4;i++)
 15             for(int j=0;j<8;j++)
 16                 if(map[i][j]!=p.map[i][j])
 17                     return false;
 18         return true;
 19     }
 20     //手写hash
 21     ll HashValue(){
 22         ll value=0;
 23         for(int i=0;i<4;i++)
 24             for(int j=0;j<8;j++)
 25                 value+=(value<<ll(1))+(ll)map[i][j];
 26         return value;
 27     }
 28 };
 29 
 30 Node Start,End;
 31 
 32 void Initaite(){
 33     memset(Hash,-1,sizeof(Hash));
 34     for(int i=0;i<4;i++){
 35         Start.map[i][0]=0;
 36         for(int j=1;j<8;j++){
 37             scanf("%d",&Start.map[i][j]);
 38         }
 39     }
 40     Start.step=0;
 41 }
 42 
 43 //最后的结果
 44 void GetEnd(){
 45     for(int i=0;i<4;i++){
 46         End.map[i][7]=0;
 47         for(int j=0;j<7;j++){
 48             End.map[i][j]=(i+1)*10+(j+1);
 49         }
 50     }
 51 }
 52 
 53 //取得value的hash值+hash判重
 54 bool HashInsert(ll value){
 55     int v=value%MAXN;
 56     while(Hash[v]!=-1&&Hash[v]!=value){
 57         v+=10;
 58         v%=MAXN;
 59     }
 60     if(Hash[v]==-1){
 61         Hash[v]=value;
 62         return true;
 63     }
 64     return false;
 65 }
 66 
 67 void bfs(){
 68     queue<Node>Q;
 69     Node p,q;
 70     Q.push(Start);
 71     HashInsert(Start.HashValue());
 72     while(!Q.empty()){
 73         p=Q.front();
 74         Q.pop();
 75         for(int i=0;i<4;i++){
 76             for(int j=0;j<8;j++){
 77                 if(!p.map[i][j]){
 78                     q=p;
 79                     q.step++;
 80                     int value=p.map[i][j-1]+1;//找比map[i][j-1]大1的数
 81                     if(value==1||value%10==8)continue;//0或者value为7的不能移动
 82                     int x,y,flag=true;
 83                     for(int k=0;k<4&&flag;k++){
 84                         for(int l=1;l<8&&flag;l++){
 85                             if(p.map[k][l]==value){
 86                                 x=k,y=l;
 87                                 flag=false;
 88                             }
 89                         }
 90                     }
 91                     if(!flag){
 92                         swap(q.map[i][j],q.map[x][y]);
 93                         ll value=q.HashValue();
 94                         //hash判重
 95                         if(HashInsert(value)){
 96                             if(q==End){
 97                                 printf("%d\n",q.step);
 98                                 return ;
 99                             }
100                             Q.push(q);
101                         }
102                     }
103                 }
104             }
105         }
106     }
107     puts("-1");
108 }
109 
110 void Solve(){
111     int k=0;
112     //将11,21,31,41这四个数移到第0列
113     for(int i=0;i<4;i++){
114         for(int j=1;j<8;j++){
115             if(Start.map[i][j]==(k+1)*10+1){
116                 swap(Start.map[i][j],Start.map[k][0]);
117                 k++,i=0,j=0;
118             }
119         }
120     }
121     if(Start==End){
122         puts("0");//前四步不记录总步数
123         return ;
124     }
125     bfs();
126 }
127 
128 int main(){
129     int _case;
130     scanf("%d",&_case);
131     GetEnd();
132     while(_case--){
133         Initaite();
134         Solve();
135     }
136     return 0;
137 }
View Code
原文地址:https://www.cnblogs.com/wally/p/3078062.html