SSL1092魔板

SSL1092魔板

在这里插入图片描述

算法

这题很明显用搜索做,但是用深搜的话容易超时甚至出现死循环,不可取。我们就只能用广搜来做了。但广搜的不足也显而易见,没有好的办法能够判断新状态是否与旧状态重合。用普通队列是完全不可能的,于是我想到了哈希表。所以这题的算法就确定下来,使用广搜+哈希。

思路

既然是搜索,就要有搜索方向。题中给出ABC三种操作,那我们应该如何实现呢?用一个[3][8]的二维数组就可以解决。{ {8,7,6,5,4,3,2,1},{4,1,2,3,6,7,8,5},{1,7,2,4,5,3,6,8}},分别代表A,B,C三种运算。
  接下来是哈希函数的设计。这个很简单,直接用除余法。主要是除数的选择。肯定要使用质数,有一种质数特别好记,31,331,3331,33331……都是质数,除了333333333331外。这道题就取333331作为除数。

代码实现

送上AC代码~~

#include<iostream>
#include<cstdio>
#define p 333331
#define maxx 1000000
using namespace std;
string h[maxx],s,state[maxx];
int f[maxx],num[maxx],tail,head; 
int rule[3][8]={
    
    {
    
    8,7,6,5,4,3,2,1},{
    
    4,1,2,3,6,7,8,5},{
    
    1,7,2,4,5,3,6,8}};
char ls[maxx];
bool hash(string s){
    
    
	int ans=0;
	for(int i=0;i<8;i++){
    
    
		ans=ans*10+s[i]-'0';
	}
	int i=0;ans%=p;
	while(i<maxx && h[(i+ans)%p]!="" && h[(i+ans)%p]!=s){
    
    
		i++;
	}
	if(h[(i+ans)%p]==""){
    
    
		h[(i+ans)%p]=s;
		return false;
	}
	else{
    
    
		return true;
	}
}
void bfs(){
    
    
	hash("12345678");
	state[1]="12345678";
	head=0;tail=1;
	do{
    
    
		head++;
		for(int i=0;i<3;i++){
    
    
			tail++; 
			f[tail]=head; 
			state[tail]=""; 
			num[tail]=num[head]+1; 
			if (i==0) ls[tail]='A'; else
			if (i==1) ls[tail]='B'; else
			if (i==2) ls[tail]='C'; 
			for(int j=0;j<8;j++){
    
    
				state[tail]+=state[head][rule[i][j]-1];
			}	
			if(hash(state[tail])) tail--;
			else if(state[tail]==s) return;
			
		}
	}while(head<tail);
}
void print(int x){
    
    
	if(x==1){
    
    
		return;
	}
	print(f[x]);
	printf("%c",ls[x]);
}
int main(){
    
    
	int xx;
	for (int i=0;i<8;i++)
	 {
    
    scanf("%d",&xx);s+=xx+48; }
	if (s=="12345678"){
    
    
		printf("0");
		return 0;
	}
	bfs(); 
	printf("%d\n",num[tail]); 
	print(tail);
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/weixin_54799322/article/details/112978795