题意:长度为8的数字序列最少移动几次达成升序,移动规则是两个数必须符号不相同且绝对值相加是素数才可以移动到一起,如果无法办到输出-1.
题解:bfs,判重用哈希就好,移动时数组的变化需要仔细写,容易出错。
#include <stdio.h>
#include <string.h>
#include <cmath>
using namespace std;
const int N = 1000000;
typedef int State[8];
State que[50000], sta;
int head[N], next[N], step[50000];
const int prime[] = {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1};
void init() {
memset(head, 0, sizeof(head));
step[0] = 0;
}
int hash(State &s) {
int v = 0;
for (int i = 0; i < 8; i++)
v = v * 10 + abs(s[i]);
return v % N;
}
int 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 0;
u = next[u];
}
next[s] = head[h];
head[h] = s;
return 1;
}
void move(State &t, int u, int v, int k) {
if (k == 1) {// u v
if (u == v - 1)
return;
else if (u == v + 1) {
int temp = t[u];
t[u] = t[v];
t[v] = temp;
}
int temp = t[u];
if (u > v) { //v u
for (int i = u; i > v; i--)
t[i] = t[i - 1];
t[v] = temp;
}
else {
for (int i = u; i < v - 1; i++)
t[i] = t[i + 1];
t[v - 1] = temp;
}
}
else {
if (u == v + 1)
return;
else if (u == v - 1) {
int temp = t[u];
t[u] = t[v];
t[v] = temp;
}
int temp = t[u];
if (u > v) {
for (int i = u; i > v + 1; i--)
t[i] = t[i - 1];
t[v + 1] = temp;
}
else {
for (int i = u; i < v; i++)
t[i] = t[i + 1];
t[v] =temp;
}
}
}
int judge(State s) {
for (int i = 0; i < 7; i++)
if (abs(s[i]) > abs(s[i + 1]))
return 0;
return 1;
}
int bfs() {
init();
int front = 0, rear = 1;
try_to_insert(front);
memcpy(que[front], sta, sizeof(sta));
while (front < rear) {
State& st = que[front];
if (judge(st))
return step[front];
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (i == j || st[i] * st[j] > 0 )
continue;
int sum = abs(st[i]) + abs(st[j]);
if (!prime[sum])
continue;
for (int k = 1; k <= 2; k++) {
State &t = que[rear];
memcpy(&t, &st, sizeof(st));
move(t, i, j, k);
if (try_to_insert(rear)) {
step[rear] = step[front] + 1;
rear++;
}
}
}
}
front++;
}
return -1;
}
int main() {
int t = 1;
while (scanf("%d", &sta[0]) && sta[0]) {
for (int i = 1; i < 8; i++)
scanf("%d", &sta[i]);
printf("Case %d: %d\n", t++, bfs());
}
}