Light OJ 1165 Digit Dancing

    
                                                                                            1165 - Digit Dancing

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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值