题目大意
给出一个2*4的矩阵,有3种基本操作
A | B | C |
---|---|---|
交换上下两行 | 将最右边的一列插入最左边 | 中央四格作顺时针旋转 |
基本状态:
1 2 3 4
8 7 6 5
给定一个目标状态,求最少的基本操作完成基本状态到目标状态的转换,输出基本操作序列。
题目解析
该题目很明显是用搜索做,如果用深搜,则会超时,所以只能用宽搜。
但是如果没有一种好的方法来判断是否已经加入列表,可能会超时,所以,哈希表。
代码
#include<iostream>
#include<string>
#define p 100003//质数
using namespace std;
int x,f[p],num[p],head,tail=1;//f标记父节点 num表示当前状态的最少操作数
int r[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 ans[p];//存储 A B C
string g,a[p],state[p];//g为目标状态
bool hash(string s)//哈希函数
{
int k=0,i=0;
for(int i=0;i<8;i++)
k=k*10+s[i]-48;
k%=p;
while(a[(k+i)%p]!=""&&a[(k+i)%p]!=s)
i++;
if(a[(i+k)%p]=="")
{
a[(i+k)%p]=s;
return false;
}
return true;
}
void bfs()
{
hash("12345678");
state[1]="12345678";//初始化
do
{
head++;
for(int i=0;i<3;i++)
{
tail++;
f[tail]=head;
state[tail]="";
num[tail]=num[head]+1;
ans[tail]='A'+i;
for(int j=0;j<8;j++)
state[tail]+=state[head][r[i][j]-1];//字符串从0为开始算
if(hash(state[tail])) tail--;//判断是否能够入队
else if(state[tail]==g) return;//找到目标状态
}
}while(head<tail);
}
void out(int x)//输出
{
if(x==1) return;
out(f[x]);
cout<<ans[x];
}
int main()
{
for(int i=1;i<=8;i++)
{
cin>>x;
g+=x+48;
}//目标状态转换为字符串
if(g=="12345678")
{
cout<<0;
return 0;
}//特判
bfs();//宽搜
cout<<num[tail]<<endl;
out(tail);
}