Digits like to dance. One day, 1, 2, 3, 4, 5, 6, 7 and 8stand in a line to have a wonderful party. Each time, a male digit can ask afemale digit to dance with him, or a female digit can ask a male digit to dancewith her, as long as their sum is a prime. Before every dance, exactly onedigit goes to who he/she wants to dance with - either to its immediate left orimmediate right.
For simplicity, we denote a male digit x by itself x, anddenote 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 isnot a prime; 2 cannot dance with 5, since they're both male.
Given the initial ordering of the digits, find the minimalnumber of dances needed for them to sort in increasing order (ignoring signs ofcourse).
Input
Input starts with an integer T (≤ 100),denoting the number of test cases.
Each case contains exactly eight integers in a single line.The absolute values of these integers form a permutation of {1, 2, 3, 4, 5,6, 7, 8}.
Output
For each test case, print the case number and the minimal numberof dances needed. If they can never be sorted in increasing order, print -1.
Sample Input | Output for Sample Input |
5 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 | Case 1: 1 Case 2: 0 Case 3: 1 Case 4: -1 Case 5: 3 |
*这个问题就是一个bfs暴力搜索,有几个问题:
1.如何判重?如何保存状态?
2.如何进行搜索?
#1:判重方法:
a.hash判重;
b.康托展开;
c.一个八维数组;
d.用map;
#2:搜索:
直接枚举队头节点状态的每两位;
具体思路:
从初始状态开始bfs,每次取队头然后删除,判断是否达到12345678的状态。
若无,则枚举这个状态的两位数字,若一正一负,且绝对值和为素数,则开始进行数字的移动,然后得到下一个状态,再判重,然后push进队列,具体细节的实现还是看代码吧:
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int is_prime[]={0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1};
int fac[]={1,1,2,6,24,120,720,5040,40320};
struct Point{
int num,flag;
};
struct Node{
Point state[10];
int step;
}st;
bool vis[400000];
int Get_Hash(Node &node)//得到每个状态的hash值,用于判重。
{
int a[10],val=0,cnt;
for(int i=0;i<8;i++)a[i]=abs(node.state[i].num);
for(int i=0;i<8;i++){
cnt=0;
for(int j=0;j<i;j++){
if(a[j]>a[i])cnt++;
}
val+=cnt*fac[i];
}
return val;
}
bool goal(Node &node)
{
for(int i=0;i<7;i++){
if(abs(node.state[i].num)>abs(node.state[i+1].num))
return false;
}
return true;
}
Node Get_Node(Node &p,int pos1,int pos2,int dir)
{
//pos1->pos2 left
Point tmp=p.state[pos1];
if(dir==0)
{
if(pos1<pos2)
{
for(int i=pos1;i<=pos2-2;i++) p.state[i]=p.state[i+1];
p.state[pos2-1]=tmp;
}else
{
for(int i=pos1;i>pos2;i--) p.state[i]=p.state[i-1];
p.state[pos2]=tmp;
}
}
else if(dir==1)
{ //pos1->pos2 right
if(pos1<pos2)
{
for(int i=pos1;i<=pos2-1;i++)
p.state[i]=p.state[i+1];
p.state[pos2]=tmp;
}else
{
for(int i=pos1;i>=pos2+2;i--) p.state[i]=p.state[i-1];
p.state[pos2+1]=tmp;
}
}
return p;
}
void bfs()
{
memset(vis,false,sizeof(vis));
queue<Node> que;
que.push(st);
vis[Get_Hash(st)]=true;
while(!que.empty())
{
Node next,tmp,now=que.front();
que.pop();
if(goal(now))
{
printf("%d\n",now.step);
return ;
}
for(int i=0;i<8;i++)
{
for(int j=0;j<8;j++)
if(i!=j)
{
if(now.state[i].flag!=now.state[j].flag&&is_prime[abs(now.state[i].num)+abs(now.state[j].num)])
{
for(int k=0;k<2;k++)
{
tmp=now;
next=Get_Node(tmp,i,j,k);
int val=Get_Hash(next);
next.step=now.step+1;
if(!vis[val])
{
vis[val]=true;
que.push(next);
}
}
}
}
}
}
puts("-1");
}
int main()
{
<span style="font-family:KaiTi_GB2312;">//</span>freopen("in.txt","r",stdin);
int T,ca=0;
scanf("%d",&T);
while(T--)
{
for(int i=0;i<8;i++)
{
scanf("%d",&st.state[i].num);
st.state[i].flag=(st.state[i].num>0?1:-1);
}
st.step=0;
printf("Case %d: ",++ca);
bfs();
}
return 0;
}