您的位置:首页 > 其它

HDU-1430 魔板

2015-09-17 10:06 344 查看

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=1430

题意:

给出一个2*4的魔板上面有1-8八个数字蛇形排列,可以有三种操作,A:上下两行互换,B:整体循环右移一个,C:中间四个顺时针旋转一下。

求给出的两个状态之间转换的最小字典序的解。

思路:

类似于八数码,八数码看这里:/article/10441338.html

但这道题的给定终点不一定又要字典序排列所以就类似于HDU-3567的八数码,因为这道题没有未知点X所以更好写一些,主体就是八数码的单向广搜打表+康托展开hash判重。

但是这题的精妙在于状态的映射,使得无论什么起始状态都可以映射到“12345678”这种状态到某种状态。

具体方法就是求出每组数据中每个数字要去的位置:

for(i=0;i<8;i++)pre[s[i]-'1']=i;
for(i=0;i<8;i++)ss[i]=pre[ss[i]-'1']+'1';
想到这个就很容易了,确实巧妙。注意这题的特判,两个串相同时输出空行。

代码:

#define N 51234

int vis
,ans
,cnt;
char s[10],ss[10];
struct node
{
char str[10];
int pos;
}tn;
struct res
{
int now,fa;
}res
;
int fac[] = {1,1,2,6,24,120,720,5040,40320};
int KT(char s[])
{
int i, j, t, sum;
sum = 0;
for (i=0; i<8; i++)
{
t = 0;
for (j=i+1; j<8; j++)
if (s[j] < s[i])
t++;
sum += t*fac[8-i-1];
}
return sum+1;
}
void changeA(char st[])
{
for(int i=0;i<4;i++){char c=st[i];st[i]=st[7-i];st[7-i]=c;}
}
void changeB(char st[])
{
char c=st[3];st[3]=st[2];st[2]=st[1];st[1]=st[0];st[0]=c;
c=st[4];st[4]=st[5];st[5]=st[6];st[6]=st[7];st[7]=c;
}
void changeC(char st[])
{
char c=st[1];st[1]=st[6];st[6]=st[5];st[5]=st[2];st[2]=c;
}
void bfs()
{
node g,h;
int t;
for(int i=0;i<8;i++)g.str[i]=i+'1';
g.pos=0; cnt=1;
memset(vis,-1,sizeof(vis));
res[0].now=-1;vis[0]=0;
queue<node> q;
while(!q.empty())q.pop();
q.push(g);
while(!q.empty())
{
g=q.front();q.pop();
h=g;
changeA(h.str);
t=KT(h.str);
if(vis[t]==-1)
{
vis[t]=cnt;h.pos=cnt;
res[cnt].now=1;res[cnt].fa=g.pos;
q.push(h);
cnt++;
}
h=g;
changeB(h.str);
t=KT(h.str);
if(vis[t]==-1)
{
vis[t]=cnt;h.pos=cnt;
res[cnt].now=2;res[cnt].fa=g.pos;
q.push(h);
cnt++;
}
h=g;
changeC(h.str);
t=KT(h.str);
if(vis[t]==-1)
{
vis[t]=cnt;h.pos=cnt;
res[cnt].now=3;res[cnt].fa=g.pos;
q.push(h);
cnt++;
}
}
}
int main()
{
int i,j,k,kk,t,x,y,z;
int pre[10];
bfs();
while(scanf("%s",s)!=EOF)
{
scanf("%s",ss);
if(strcmp(s,ss)==0)
{
puts("");
continue;
}
for(i=0;i<8;i++)pre[s[i]-'1']=i; for(i=0;i<8;i++)ss[i]=pre[ss[i]-'1']+'1';
t = vis[KT(ss)];
i=0;
while(res[t].now!=-1)
{
ans[i++]=res[t].now-1;
t = res[t].fa;
}
for(j=i-1;j>=0;j--)
printf("%c",'A'+ans[j]);
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: