HDU 1430 魔板

題目:魔板

鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1430

題意:(中文題)

思路:

  BFS哈希打表+映射

  哇。。好題啊,映射沒想到。由於題目是求狀態S到狀態T的最短路,所以一開始就把打表排除了,後來看題解說可以映射+打表,因爲每一步的行動和數字沒關係,因此假設給出的是87654321,可以把8當作1,7當作2,。。。,1當作8,然後對T也作相應變化,這樣一來,就可以用12345678廣搜打表。

AC代碼:

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<string>
  4 #include<queue>
  5 #include<iostream>
  6 using namespace std;
  7 #define Mod 1000007    //取模的大小,哈希表的大小...
  8 #define Max 100007     //存放的總數
  9 
 10 class Hash             //手寫哈希
 11 {
 12   public:
 13     int hs[Mod];       //哈希值  設定的哈希函數爲 原值 % Mod ,所以哈希值有可能是 0 ~ Mod-1
 14     int next[Max];     //鏈表    存放哈希值相等的一條鏈,他的大小取決於所有原值的數量
 15     int S[Max];        //存放原值
 16     string V[Max];     //存放原值對應的val值
 17     int H[Max];        //存放所有哈希值
 18     int sn;            //不同原值的數量
 19     int hn;            //不同哈希值的數量
 20     Hash()             //構造函數: 定義Hash類變量時初始化
 21     {
 22       sn=0;
 23       hn=0;
 24       memset(hs, 0, sizeof(hs));
 25     }
 26     void clear()       //清空函數
 27     {
 28       sn=0;
 29       for(int i=0;i<hn;i++)
 30         hs[H[i]]=0;
 31       hn=0;
 32     }
 33     void add(int s, string val) //加入
 34     {
 35       int ha=s%Mod;          //計算哈希值
 36       if(hs[ha]==0)          //如果該哈希值還未出現過
 37       {
 38         H[hn++]=ha;          //將該哈希值記錄起來,同時哈希值數量加 1
 39       }
 40       sn++;                  //0 表示結尾,所以從1 開始存,原值數量加 1,特別針對 hs數組
 41       S[sn]=s;               //將原值記錄起來
 42       V[sn]=val;
 43       next[sn]=hs[ha];       //原本原值記錄位置
 44       hs[ha]=sn;             //最新原值記錄位置,如果從0 開始存,就無法判斷此時是空還是1個值
 45 
 46       //比如:5 和 10 有一樣的哈希值 ,並且 5 和 10 先後加入 那麼有:
 47       //5 加入: next[1] = 0; hs[5] = 1; hs[5] 是哈希值爲5 的頭,表示第一個原值在1的位置
 48       //10加入: next[2] = 1; hs[5] = 2; 表示第一個哈希值爲5的在2,第二個在1,第三個不存在
 49     }
 50     int find(int s)           //查找
 51     {
 52       int ha=s%Mod;     //計算哈希值
 53       int k=hs[ha];          //
 54       while(k!=0)
 55       {
 56         if(S[k]==s) return 1;//找到
 57         k=next[k];           //下一個節點
 58       }
 59       return 0;              //表示沒找到
 60     }
 61     string get(int s){
 62       int ha=s%Mod;     //計算哈希值
 63       int k=hs[ha];          //
 64       while(k!=0)
 65       {
 66         if(S[k]==s) return V[k];//找到
 67         k=next[k];           //下一個節點
 68       }
 69       return "";              //表示沒找到
 70     }
 71 };
 72 
 73 int change(int s){
 74   return s%10*1000 + s%100/10*100 + s%1000/100*10 + s%10000/1000;
 75 }
 76 
 77 int move(int s, int i){
 78   int gao = s/10000;
 79   int di = change(s%10000);
 80   if(i==1) return di*10000+change(gao);
 81   else if(i==2){
 82     gao = gao/10 + gao%10*1000;
 83     di = di/10 + di%10*1000;
 84   }
 85   else if(i==3){
 86     int tmp1 = gao%1000/10*10;
 87     int tmp2 = di%1000/10*10;
 88     gao -= tmp1;
 89     di -= tmp2;
 90     gao += tmp2/100*100 + tmp1/100*10;
 91     di += tmp2%100/10*100 + tmp1%100/10*10;
 92   }
 93   return gao*10000+change(di);
 94 }
 95 
 96 string get(int i){
 97   if(i==1) return "A";
 98   else if(i==2) return "B";
 99   else return "C";
100 }
101 
102 Hash hs;
103 queue<int> q;
104 void bfs(int s){
105   hs.add(s, "");
106   q.push(s);
107   while(q.size()){
108     int a=q.front();
109     q.pop();
110     string ax=hs.get(a);
111     for(int i=1; i<=3; i++){
112       int b=move(a, i);
113 
114       if(hs.find(b)==0){
115         hs.add(b, ax+get(i));
116         q.push(b);
117       }
118     }
119   }
120 }
121 
122 int main(){
123   bfs(12345678);
124   int s, t;
125   while(~scanf("%d%d", &s, &t)){
126     int c[10], k=1;
127     for(int i=0; i<8; i++){
128       c[s/k%10]=8-i;
129       k=k*10;
130     }
131     k=1;
132     for(int i=0; i<8; i++){
133       t=t-t/k%10*k+c[ t/k%10 ]*k;
134       k=k*10;
135     }
136 
137     cout << hs.get(t) << endl;
138   }
139   return 0;
140 }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章