Digits like to dance. One day, 1, 2, 3, 4, 5, 6, 7 and 8 stand in a line to have a wonderful party. Each time, a male digit can ask a female digit to dance with him, or a female digit can ask a male digit to dance with her, as long as their sum is a prime. Before every dance, exactly one digit goes to who he/she wants to dance with - either to its immediate left or immediate right.
For simplicity, we denote a male digit x by itself x, and denote a female digit x by -x. Suppose the digits are in order {1, 2, 4, 5, 6, -7, -3, 8}. If -3 wants to dance with 4, she must go either to 4's left, resulting {1, 2, -3, 4, 5, 6, -7, 8} or his right, resulting {1, 2, 4, -3, 5, 6, -7, 8}. Note that -3 cannot dance with 5, since their sum 3+5=8 is not a prime; 2 cannot dance with 5, since they're both male.
Given the initial ordering of the digits, find the minimal number of dances needed for them to sort in increasing order (ignoring signs of course).
The input consists of at most 20 test cases. Each case contains exactly 8 integers in a single line. The absolute values of these integers form a permutation of {1, 2, 3, 4, 5, 6, 7, 8}. The last case is followed by a single zero, which should not be processed.
For each test case, print the case number and the minimal number of dances needed. If they can never be sorted in increasing order, print -1.
1 2 4 5 6 -7 -3 8 1 2 3 4 5 6 7 8 1 2 3 5 -4 6 7 8 1 2 3 5 4 6 7 8 2 -8 -4 5 6 7 3 -1 0
Case 1: 1 Case 2: 0 Case 3: 1 Case 4: -1 Case 5: 3
解题思路:隐式图搜索+哈稀判断重复,对于每个状态,对每个数字开始遍历,找到与之“可邀请的数字”,移动到它的左边和右边(都要考虑),一开始很快就写好了,但是在判重的函数中将memcmp写成了memcpy,结果案例过了,交上去总是RE,因为判重的作用没有了。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> using namespace std; typedef int State[8]; const int MAXN = 1000005; const int prime[20] = {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1}; State order, rec, g[50000]; int head[MAXN], next[MAXN], dist[MAXN]; int cmp(const int &a, const int &b) { return abs(a) < abs(b); } void inInit() { memset(head, 0, sizeof(head)); dist[0] = 0; memcpy(g[1], rec, sizeof(rec)); } void inSert(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; } } } int hash(State now) { int sum = 0; for (int i = 0; i < 8; i++) sum = sum * 10 + now[i]; return (sum & 0x7FFFFFFF) % MAXN; } bool tryInsert(int cur) { int h = hash(g[cur]); int u = head[h]; while (u) { if(memcmp(g[u], g[cur], sizeof(g[cur])) == 0) return false; u = next[u]; } next[cur] = head[h]; head[h] = cur; return true; } int bfs() { inInit(); int front = 1, rear = 2; while (front < rear) { State& now = g[front]; if (memcmp(now, order, sizeof(order)) == 0) return dist[front]; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { if (i != j && prime[abs(now[i]) + abs(now[j])] && now[i] * now[j] < 0){ for (int dir = 1; dir <= 2; dir++) { State& next = g[rear]; memcpy(&next, &now, sizeof(now)); inSert(next, i, j, dir); if (tryInsert(rear)) dist[rear++] = dist[front] + 1; } } } } front++; } return -1; } int main(){ int cas = 1; while (scanf("%d", &rec[0]) == 1 && rec[0]) { // Read; for (int i = 1; i < 8; i++) scanf("%d", &rec[i]); memcpy(order, rec, sizeof(rec)); sort(order, order + 8, cmp); int flag = bfs(); printf("Case %d: %d\n", cas++, flag); } return 0; }