題目:Bridged Marble Ringsphp
連接:http://acm.hdu.edu.cn/showproblem.php?pid=2174算法
題意:如圖,要把全部灰色球移動到上圈,每次操做能夠轉圖中虛線圈起的三個圓,求中間圓的最少轉數。題目給出的是字符串,g表明灰色球,y表明黃色球,起始位置看標記。數組
思路:函數
BFS打表+最小表示法spa
令g=1,y=0,用int 表示當前狀態。code
最開始直接用BFS打表,超時超內存,按我最初的算法,全部狀態總數爲C(26,13)約等於1000多萬種。但實際上,由於轉動上下兩個圈是不增長轉數的,因此不少狀況是等價的,能夠壓縮狀態數,對於一個狀態S,能夠轉動上圈,下圈使其獲得最小表示的狀態T。接着存T就能夠了。每次,注意,map會超時,後面我改爲哈希就過了。。。blog
具體:每次出隊一個狀態,將該狀態對應的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 }