【CJOJ1372】【洛谷2730】【USACO 3.2.5】魔板

来源:互联网 发布:云计算开发语言 编辑:程序博客网 时间:2024/06/03 19:40

题面

Description

在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板。这是一张有8个大小相同的格子的魔板:

1 2 3 4
8 7 6 5

我们知道魔板的每一个方格都有一种颜色。这8种颜色用前8个正整数来表示。可以用颜色的序列来表示一种魔板状态,规定从魔板的左上角开始,沿顺时针方向依次取出整数,构成一个颜色序列。对于上图的魔板状态,我们用序列(1,2,3,4,5,6,7,8)来表示。这是基本状态。

这里提供三种基本操作,分别用大写字母“A”,“B”,“C”来表示(可以通过这些操作改变魔板的状态):

“A”:交换上下两行;
“B”:将最右边的一列插入最左边;
“C”:魔板中央四格作顺时针旋转。

下面是对基本状态进行操作的示范:

A:
8 7 6 5
1 2 3 4
B:
4 1 2 3
5 8 7 6
C:
1 7 2 4
8 6 3 5

对于每种可能的状态,这三种基本操作都可以使用。

你要编程计算用最少的基本操作完成基本状态到目标状态的转换,输出基本操作序列。

Input

只有一行,包括8个整数,用空格分开(这些整数在范围 1——8 之间)不换行,表示目标状态。

Output

Line 1: 包括一个整数,表示最短操作序列的长度。

Line 2: 在字典序中最早出现的操作序列,用字符串表示,除最后一行外,每行输出60个字符。

Sample Input

2 6 8 4 5 7 3 1

Sample Output

7
BCABCCB

题解

看到题目,很容易就可以想到使用BFS
而状态最多只有8!中,不到50000
完全可以使用数组直接存储
但是我用的是状压(有点麻烦自己。。。。)
然后使用map判重(用康托展开也可以的)
用了STL效率偏低
但是能够AC
其中一定要注意顺序和编号的问题(细节!)

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<vector>#include<map>#include<algorithm>using namespace std;struct Node{      int st;//步数      int t;//状态      int ff;//父节点      char way;//方式 }Q[50000];int h,t;int End,Beg=12348765;//bool vis[50000];map<int,bool> vis;inline int read(){       register int x=0,t=1;register char ch=getchar();       while(ch<'0'||ch>'9')ch=getchar();       while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}       return x;}int ten[8]={1,10,100,1000,10000,100000,1000000,10000000};int change(int tt,int x,int y)//交换状态tt的x位和y位{        int ttt=tt,a,b;        for(int i=1;i<x;++i)           ttt/=10;        a=ttt%10;        for(int i=x;i<y;++i)           ttt/=10;        b=ttt%10;        return tt-(a-b)*ten[x-1]+(a-b)*ten[y-1];}void outp(int t){        vector<Node> Ans;        while(t!=1)        {               Ans.push_back(Q[t]);               t=Q[t].ff;        }        int si=Ans.size();        cout<<si<<endl;        for(int i=0;i<si;++i)        {             cout<<Ans[si-i-1].way;             if(i%60==59)cout<<endl;        }}int main(){        for(int i=8;i>=5;--i)           End+=(read()*ten[i-1]);        for(int i=1;i<=4;++i)           End+=(read()*ten[i-1]);        Q[1]=(Node){0,Beg,0,0};        if(Beg==End)//初始时相同        {                 printf("0\n");                 return 0;        }        vis[Beg]=true;        h=0,t=1;        while(h<t)        {                 Node now=Q[++h];                 int s;                 //变化A                 s=now.t;                 for(int i=1;i<=4;++i)                    s=change(s,i,i+4);//上下交换                 if(vis.find(s)==vis.end())//没有访问过                 {                         vis[s]=true;                         Q[++t]=(Node){now.st+1,s,h,'A'};                 }                 if(s==End)                 {                         outp(t);                         return 0;                 }                               //变化B                 s=now.t;                 for(int i=1;i<=3;++i)                    s=change(s,i,i+1);                 for(int i=5;i<=7;++i)                    s=change(s,i,i+1);                 if(vis.find(s)==vis.end())                 {                         vis[s]=true;                         Q[++t]=(Node){now.st+1,s,h,'B'};                 }                 if(s==End)                 {                         outp(t);                         return 0;                 }                       //变化C                 s=now.t;                  s=change(s,2,3);                 s=change(s,2,7);                 s=change(s,2,6);                 if(vis.find(s)==vis.end())                 {                         vis[s]=true;                         Q[++t]=(Node){now.st+1,s,h,'C'};                 }                 if(s==End)                 {                         outp(t);                         return 0;                 }              }        return 0;}
原创粉丝点击