题意:给你一个排列,让你排序成绝对值从小到达的最小步数,交换条件是,两位是异号,并且和为素数,看了别人的哈希,就用哈希保存所有的情况
#include <iostream> #include <cstring> #include <cstdio> #include <cmath> using namespace std; const int HashSize = 1000003 ; typedef int State[8]; State start ; State que[50000]; int head[HashSize],next[HashSize],step[50000],ans; int prim[16]={0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0}; inline void init_lookup_table() { ans = -1 ; step[0] = 0 ; memset(head,0,sizeof(head)); } inline int hash(State &s) { int v = 0 ; for (int i = 0 ; i < 8 ; i++) v = v*10 +abs(s[i]); return( v & 0x7FFFFFFF ) % HashSize; } inline bool try_to_insert(int s) { int h = hash(que[s]); int u = head[h]; while ( u ) { if ( memcmp(que[u],que[s],sizeof(que[s])) == 0 ) return false ; u = next[u]; } next[s] = head[h]; head[h] = s ; return true; } bool is_ok(State &s) { for (int i = 0 ; i < 7 ; i++) if ( abs(s[i])>abs(s[i+1])) return false ; return true; } void goto_dance(State &s,int u,int v,int dir) { if (dir == 1) { if (u == v-1) return ; if (u == v+1) { int tmp = s[u]; s[u] = s[v]; s[v] = tmp; } int t=s[u]; if (u > v) { for (int i = u ; i > v ; i--) s[i] = s[i-1]; s[v] = t; } else { for (int i = u ; i < v-1 ; i++) s[i] = s[i+1]; s[v-1] = t ; } } else { if (u == v+1) return ; if (u == v-1) { int tmp = s[u]; s[u] = s[v]; s[v] = tmp; } int t = s[u]; if (u > v) { for (int i = u ; i >v+1 ;i--) s[i] = s[i-1]; s[v+1] = t ; } else { for (int i = u ; i < v ; i++) s[i] = s[i+1]; s[v] = t ; } } } void bfs() { init_lookup_table(); int front=0,rear=1; memcpy(que[0],start,sizeof(start)); try_to_insert(0); while (front < rear) { State &s = que[front]; if (is_ok(s)) { ans = step[front]; return ; } for (int i = 0 ; i < 8 ; i++) { for (int j = 0 ; j < 8 ; j++) if ( i != j && ((s[i] < 0 && s[j] >0) ||( s[i] > 0 && s[j] < 0 ))) { int sum = abs(s[i]) + abs(s[j]) ; if ( !prim[sum]) continue; for (int k = 1 ; k <= 2 ; k++) { State &t = que[rear]; memcpy(t,s,sizeof(s)); goto_dance(t,i,j,k); if (try_to_insert(rear)) { step[rear] = step[front] + 1; rear++; } } } } ++front; } } int main() { int cas = 1; while (scanf("%d",&start[0]) != EOF && start[0]) { for (int i = 1 ; i < 8 ; i++) scanf("%d",&start[i]); bfs(); printf("Case %d: %d\n",cas++,ans); } return 0; }