uva 11198

题意:给你一个排列,让你排序成绝对值从小到达的最小步数,交换条件是,两位是异号,并且和为素数,看了别人的哈希,就用哈希保存所有的情况

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;

const int HashSize = 1000003 ;
typedef int State[8];
State start ;
State que[50000];
int head[HashSize],next[HashSize],step[50000],ans;
int prim[16]={0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0}; 

inline void init_lookup_table()
{
	ans = -1 ;
	step[0] = 0 ;
	memset(head,0,sizeof(head));
}

inline int hash(State &s)
{
	int v = 0 ;
	for (int i = 0 ; i < 8 ; i++)
		v = v*10 +abs(s[i]);
	return( v & 0x7FFFFFFF ) % HashSize;
}

inline bool 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 false ;
		u = next[u];
	}
	next[s] = head[h];
	head[h] = s ;
	return true;
}	

bool is_ok(State &s)
{
	for (int i = 0 ; i < 7 ; i++)
		if ( abs(s[i])>abs(s[i+1]))
			return false ;
	return true;
}

void goto_dance(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 ;
		}
	}
}

void bfs()
{
	init_lookup_table();
	int front=0,rear=1;
	memcpy(que[0],start,sizeof(start));
	try_to_insert(0);
	while (front < rear)
	{
		State &s = que[front];
		if (is_ok(s))
		{
			ans = step[front];
			return ;
		}
		for (int i = 0 ; i < 8 ; i++)
		{
			for (int j = 0 ; j < 8 ; j++)
				if ( i != j && ((s[i] < 0 && s[j] >0) ||( s[i] > 0 && s[j] < 0 )))
				{
					int sum = abs(s[i]) + abs(s[j]) ;
					if ( !prim[sum])
						continue;
					for (int k = 1 ; k <= 2 ; k++)
					{
						State &t = que[rear];
						memcpy(t,s,sizeof(s));
						goto_dance(t,i,j,k);
						if (try_to_insert(rear))
						{
							step[rear] = step[front] + 1;
							rear++;
						}
					}
				}
		}
		++front;
	}
}

int main()
{
	int cas = 1;
	while (scanf("%d",&start[0]) != EOF && start[0])
	{
		for (int i = 1 ; i < 8 ; i++)
			scanf("%d",&start[i]);
		bfs();
		printf("Case %d: %d\n",cas++,ans);
	}
	return 0;
}



你可能感兴趣的:(uva 11198)