[USACO3.2.5 Magic Squares]

[关键字]:搜索

[题目大意]:给出一个魔版的目标状态,求利用A、B、C三种操作用最小步数有初始状态走到的序列(字典序最小)。

//================================================================================================================

[分析]:利用BFS扩展,Hash判重,还可用康托展开,但我不会……这个我是在不想说什么,就是超级简化版的八数码……

[代码]:

View Code
/*
ID:procedure2
PROB:msquare
LANG:C++
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

struct node
{
int f,d;
int dat[8];
}q[1000000];
int h[400000][10];
int goal[8],now[8]={1,2,3,4,5,6,7,8};

bool Hash(int *a)
{
int k,m=0;
for (int i=0;i<8;i++) m=m*10+a[i];
k=m%399997;
for (int i=1;i<=h[k][0];i++)
if (h[k][i]==m) return 1;
h[k][++h[k][0]]=m;
return 0;
}

void Change(int *a,int f)
{
if (f==1)
{
for (int i=0;i<=3;i++) swap(a[i],a[7-i]);
}
if (f==2)
{
int t=a[3];
for (int i=3;i>0;i--) a[i]=a[i-1];
a[0]=t;
t=a[4];
for (int i=4;i<7;i++) a[i]=a[i+1];
a[7]=t;
}
if (f==3)
{
int t=a[1];
a[1]=a[6];
a[6]=a[5];
a[5]=a[2];
a[2]=t;
}
return;
}

bool Cleck(int *a)
{
for (int i=0;i<8;i++) if (a[i]!=goal[i]) return 0;
return 1;
}

void Print(int x,int y)
{
if (x==1) {printf("%d\n",y);return;}
Print(q[x].f,y+1);
if (q[x].d==1) printf("A");
if (q[x].d==2) printf("B");
if (q[x].d==3) printf("C");
}

int BFS()
{
int head=1,t=1;
memcpy(q[1].dat,now,sizeof(now));
Hash(q[1].dat);
while (head<=t)
{
for (int i=1;i<=3;i++)
{
memcpy(now,q[head].dat,sizeof(now));
Change(now,i);
if (!Hash(now))
{
//for (int y=0;y<8;y++) printf("%d ",now[y]);
//printf("\n");
memcpy(q[++t].dat,now,sizeof(now));
q[t].f=head;
q[t].d=i;
}
if (Cleck(now)) return t;
}
head++;
}
return 0;
}

int main()
{
freopen("input8.txt","r",stdin);
freopen("out.txt","w",stdout);
for (int i=0;i<8;i++) scanf("%d",&goal[i]);
if (Cleck(now)) printf("%d",0); else Print(BFS(),0);
printf("\n");
return 0;
}



你可能感兴趣的:(USACO)