HDU 2174 Bridged Marble Rings

題目:Bridged Marble Rings

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

題意:如圖,要把所有灰色球移動到上圈,每次操作可以轉圖中虛線圈起的三個圓,求中間圓的最少轉數。題目給出的是字符串,g代表灰色球,y代表黃色球,起始位置看標記。

思路:

  BFS打表+最小表示法

  令g=1,y=0,用int 表示當前狀態。

  最開始直接用BFS打表,超時超內存,按我最初的算法,所有狀態總數爲C(26,13)約等於1000多萬種。但實際上,因爲轉動上下兩個圈是不增加轉數的,所以很多情況是等價的,可以壓縮狀態數,對於一個狀態S,可以轉動上圈,下圈使其得到最小表示的狀態T。接着存T就可以了。每次,注意,map會超時,後面我改成哈希就過了。。。

  具體:每次出隊一個狀態,將該狀態對應的13*13個下一步狀態(篩選一下)入隊。

AC代碼:

  1 #include<stdio.h>
  2 #include<map>
  3 #include<queue>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 #define Mod 1000007     //取模的大小,哈希表的大小...
  8 #define Max 100007         //存放的總數
  9 typedef long long LL;
 10 class Hash             //手寫哈希
 11 {
 12   public:
 13     int hs[Mod];       //哈希值  設定的哈希函數爲 原值 % Mod ,所以哈希值有可能是 0 ~ Mod-1
 14     int next[Max];     //鏈表    存放哈希值相等的一條鏈,他的大小取決於所有原值的數量
 15     LL S[Max];         //存放原值
 16     int H[Max];        //存放所有哈希值
 17     int sn;            //不同原值的數量
 18     int hn;            //不同哈希值的數量
 19     Hash()             //構造函數: 定義Hash類變量時初始化
 20     {
 21       sn=0;
 22       hn=0;
 23       for(int i=0;i<Mod;i++)
 24         hs[i]=0;
 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(LL s)           //加入
 34     {
 35       int ha=abs(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       next[sn]=hs[ha];       //原本原值記錄位置
 43       hs[ha]=sn;             //最新原值記錄位置,如果從0 開始存,就無法判斷此時是空還是1個值
 44       //比如:5 和 10 有一樣的哈希值 ,並且 5 和 10 先後加入 那麼有:
 45       //5 加入: next[1] = 0; hs[5] = 1; hs[5] 是哈希值爲5 的頭,表示第一個原值在1的位置
 46       //10加入: next[2] = 1; hs[5] = 2; 表示第一個哈希值爲5的在2,第二個在1,第三個不存在
 47     }
 48     int find(LL s)           //查找
 49     {
 50       int ha=abs(s)%Mod;     //計算哈希值
 51       int k=hs[ha];          //
 52       while(k!=0)
 53       {
 54         if(S[k]==s) return k;//找到
 55         k=next[k];           //下一個節點
 56       }
 57       return 0;              //表示沒找到
 58     }
 59 };
 60 
 61 int move(int s, int i){
 62   int gao = (s>>13)&0x1FFF;
 63   int di = s&0x1FFF;
 64   if(i==0){
 65     int tmp = di&1;
 66     di = di >> 1;
 67     di = di | (tmp << 12);
 68   }
 69   else if(i==1){
 70     int tmp = gao&1;
 71     gao = gao >> 1;
 72     gao = gao | (tmp << 12);
 73   }
 74   else{
 75     int a = (gao & 0x1C00)>>10;
 76     int b = (di & 0x1C00)>>10;
 77     gao = gao & 0x3FF;
 78     di = di & 0x3FF;
 79     gao = (b<<10)| gao;
 80     di = (a<<10) | di;
 81   }
 82   return (gao<<13)|di;
 83 }
 84 
 85 map<int, int> mp;
 86 int c[1<<13];
 87 
 88 int min_code(int s){
 89   int gao = (s>>13)&0x1FFF;
 90   int di = s&0x1FFF;
 91   gao = c[gao];
 92   di = c[di];
 93   return (gao<<13)|di;
 94 }
 95 int min_code_1(int s){
 96   int ms=s;
 97   for(int i=0; i<12; i++){
 98     int tmp = s&1;
 99     s >>= 1;
100     s = s | (tmp << 12);
101     if(ms>s) ms=s;
102   }
103   return ms;
104 }
105 
106 Hash hs;
107 queue<int> q;
108 
109 void mov(int ms){
110   int a=ms;
111   for(int i=0; i<13; i++){
112     a=move(a, 0);
113     int b=a;
114     for(int j=0; j<13; j++){
115       b=move(b, 1);
116       int c=move(b, 2);
117       int mc=min_code(c);
118       int cx=hs.find(mc);
119       if(cx==0){
120         hs.add(mc);
121         mp[mc]=mp[ms]+1;
122         q.push(mc);
123       }
124     }
125   }
126 }
127 
128 void bfs(int s){
129   s=min_code(s);
130   mp[s]=1;
131   q.push(s);
132   while(q.size()){
133     int a=q.front();
134     q.pop();
135     mov(a);
136   }
137 }
138 
139 int main(){
140   for(int i=0; i<(1<<13); i++){
141     c[i]=min_code_1(i);
142   }
143   int t=0x3FFE000;
144   bfs(t);
145   char tmp[30];
146   while(~scanf("%s", tmp)){
147     int s=0;
148     for(int i=0; tmp[i]; i++){
149       if(tmp[i]=='g') s=s*2+1;
150       else s=s*2;
151     }
152 
153     if(s==t) printf("0\n");
154     else printf("%d\n", mp[min_code(s)]-1);
155   }
156   return 0;
157 }

 

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