首先这道题目需要用到全排列的哈希这个知识点,只要对排列的哈希可以解决,那么剩下的就是广搜加优先队列寻找最短路径的问题了问题,在状态进行扩展的时候注意每一次的状态拓展要找到当前状态下所有可以进行配对的两个节点,然后两个节点之间进行四种位置的变换,生成所有下一步可能的状态,这样利用广搜加优先队列的方法,问题就得到解决了。
#include <stdio.h>
#include <queue>
#include <set>
#include <string.h>
using namespace std;
int jiecheng[9] = {0, 1, 2, 6, 24, 120, 720, 5040, 40320};
int case_count;
struct node
{
char data[8];
int step;
};
bool visited[40320];
set<int> prime;
int my_abs(int n)
{
return n<0 ? n*-1:n;
}
int my_hash(const struct node &n)
{
int sum = 0;
int i, j, count;
for(i=0; i<=6; i++)
{
count = my_abs(n.data[i])-1;
for(j=0; j<i; j++)
{
if( my_abs(n.data[j]) < my_abs(n.data[i]))
count --;
}
sum += jiecheng[7-i] * count;
}
return sum;
}
bool operator < (const struct node &a, const struct node &b)
{
return a.step > b.step;
}
priority_queue< struct node > pq;
int bfs()
{
struct node my_node, new_node;
int step;
int i, j, ii, jj;
int num1, num2, num_i, num_j;
bool find_target;
find_target = false;
while(!pq.empty())
{
memcpy(&my_node, &(pq.top()), sizeof(struct node));
pq.pop();
/*
printf("pop:");
for(int k=0; k<=7; k++)
printf("%d ", my_node.data[k]);
printf("step=%d\n", my_node.step);
*/
step = my_node.step;
if(my_hash(my_node) == 0)
{
find_target = true;
break;
}
for(i=0; i<=6; i++)
{
for(j=i+1; j<=7; j++)
{
num1 = my_node.data[i];
num2 = my_node.data[j];
if(num1>0&&num2>0 || num1<0&&num2<0)
continue;
num1 = my_abs(num1);
num2 = my_abs(num2);
if(prime.find(num1+num2) != prime.end())
{
//j放到i的左边
memcpy(&new_node, &my_node, sizeof(struct node));
num_j = new_node.data[j];
for(ii=j; ii>=i+1; ii--)
new_node.data[ii] = new_node.data[ii-1];
new_node.data[i] = num_j;
if(!visited[my_hash(new_node)])
{
visited[my_hash(new_node)] = true;
new_node.step = step + 1;
/*
printf("new node:");
for(int k=0; k<=7; k++)
printf("%d ", new_node.data[k]);
printf("step=%d\n", my_node.step);
*/
pq.push(new_node);
}
//j放到i的右边
memcpy(&new_node, &my_node, sizeof(struct node));
num_j = new_node.data[j];
for(ii=j; ii>=i+2; ii--)
new_node.data[ii] = new_node.data[ii-1];
new_node.data[i+1] = num_j;
if(!visited[my_hash(new_node)])
{
visited[my_hash(new_node)] = true;
new_node.step = step + 1;
/*
printf("new node:");
for(int k=0; k<=7; k++)
printf("%d ", new_node.data[k]);
printf("step=%d\n", my_node.step);
*/
pq.push(new_node);
}
//i放到j的左边
memcpy(&new_node, &my_node, sizeof(struct node));
num_i = new_node.data[i];
for(ii=i; ii<=j-2; ii++)
new_node.data[ii] = new_node.data[ii+1];
new_node.data[j-1] = num_i;
if(!visited[my_hash(new_node)])
{
visited[my_hash(new_node)] = true;
new_node.step = step + 1;
/*
printf("new node:");
for(int k=0; k<=7; k++)
printf("%d ", new_node.data[k]);
printf("step=%d\n", my_node.step);
*/
pq.push(new_node);
}
//i放到j的右边
memcpy(&new_node, &my_node, sizeof(struct node));
num_i = new_node.data[i];
for(ii=i; ii<=j-1; ii++)
new_node.data[ii] = new_node.data[ii+1];
new_node.data[j] = num_i;
if(!visited[my_hash(new_node)])
{
visited[my_hash(new_node)] = true;
new_node.step = step + 1;
/*
printf("new node:");
for(int k=0; k<=7; k++)
printf("%d ", new_node.data[k]);
printf("step=%d\n", my_node.step);
*/
pq.push(new_node);
}
}
}
}
}
if(find_target)
return step;
else
return -1;
}
void func(const struct node &n)
{
struct node my_node;
memcpy(&my_node, &n, sizeof(struct node));
memset((void*)visited, false, 40320);
while(!pq.empty())
pq.pop();
pq.push(my_node);
visited[my_hash(my_node)] = true;
printf("Case %d: %d\n", case_count, bfs());
}
int main(void)
{
//freopen("input.dat", "r", stdin);
struct node n;
prime.insert(2);
prime.insert(3);
prime.insert(5);
prime.insert(7);
prime.insert(11);
prime.insert(13);
case_count = 0;
while(1)
{
scanf("%d", n.data);
if(n.data[0] == 0)
break;
for(int i=1; i<=7; i++)
scanf("%d", n.data+i);
n.step = 0;
case_count ++;
func(n);
}
return 0;
}