1 条题解

  • 1
    @ 2023-3-2 13:48:12

    原文链接(也是我写的):【BFS】魔板(c++基础算法)_静渊隐者的博客-CSDN博客

    做题

    题意 很显然,这道题是让我们求12345678经过三种变化,到目标状态 的步数与变化操作。

    ①算法原理

    这题与【BFS】八数码问题极其相似,我就在讲论两者间的区别中,来把这题讲给你。

    ②算法实现

    Ⅰ三种基本操作

    相对于八数码的空格上下左右操作,这题有三种不同的操作。

    “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

    看到很多人都是用二维数组来搞,但我觉得没有必要。我直接在main函数中,利用switch()语句来进行。

    “A”功能:循环j从1-4,交换a[j] 与a[9-j]。

    “B”功能:循环j从1-3,交换a[j],a[4],和a[9-j],a[5].(不断对第j列[j会不断加1]和最后一列交换,最终达成目的)

    “C”功能,直接换来换去。

    {
    case 1:
    for(int i=1;i<=4;i++)
    {
    swap(ne.a[i],ne.a[9-i]);
    }
    break;
    case 2:
    for(int i=1;i<=3;i++)
    {
    swap(ne.a[i],ne.a[4]);
    swap(ne.a[9-i],ne.a[5]);
    }
    break;
    case 3:
    swap(ne.a[3],ne.a[6]);
    swap(ne.a[7],ne.a[3]);
    swap(ne.a[3],ne.a[2]);
    }
    

    Ⅱ操作序列

    我将每钟情况都赋予一个序列。当此情况可行(之前没出现过),先将其上一步序列赋值到它身上,在增加此次操作的序列。

    for(int k=1;k<=q.front().ans;k++) 
    
    ```ne.bz[k]=q.front().bz[k];
    ne.bz[ne.ans]=i;
    

    Ⅲ输出 先将操作次数输出,再对序列操作,然后输出。

    对序列的操作:原有基础上,强制转换为字符,加上‘A’,减一(因为序列数为1时应输出A,而不建议会变为B,因此要减一)

    {
    printf("%d\n",q.back().ans);
    for(int k=1;k<=q.back().ans;k++) printf("%c",q.back().bz[k]+'A'-1);
    exit(0);
    }
    

    Ⅳ一个特殊情况

    当目标状态与初始状态一样时,会无法进入我的输出语句。因此要在结尾输出一个0(因为当出现上述情况时,无需操作即可达到目标状态)

    四.AC代码

    不写注释啦!

    using namespace std;
    struct node{
    int kt,ans,bz[1005];
    int a[10];
    }st,ed;
    bool b[50000];
    queueq;
    long kt(node t)
    {
    long long s=1;
    for(int i=1;i<=8;i++)
    {
    int index=1,f=1,count=0;
    for(int j=i+1;j<=8;j++)
    {
    if(t.a[i]>t.a[j]) count++;
    f*=index++;
    }
    s=s+f*count;
    }
    return s;
    }
    int main()
    {
    for(int i=1;i<=8;i++) st.a[i]=i;
    
    st.kt=kt(st);
    b[st.kt]=1;
    for(int i=1;i<=8;i++) scanf("%d",&ed.a[i]);
    ed.kt=kt(ed);
    q.push(st);
    while(!q.empty())
    {
    for(int i=1;i<=3;i++)
    {
    node ne=q.front();
    switch(i)
    {
    case 1:
    for(int i=1;i<=4;i++)
    {
    swap(ne.a[i],ne.a[9-i]);
    }
    break;
    case 2:
    for(int i=1;i<=3;i++)
    {
    swap(ne.a[i],ne.a[4]);
    swap(ne.a[9-i],ne.a[5]);
    }
    break;
    case 3:
    swap(ne.a[3],ne.a[6]);
    swap(ne.a[7],ne.a[3]);
    swap(ne.a[3],ne.a[2]);
    }
    ne.ans++;
    ne.kt=kt(ne);
    if(!b[ne.kt])
    {
    
    for(int k=1;k<=q.front().ans;k++) ne.bz[k]=q.front().bz[k];
    ne.bz[ne.ans]=i;
    b[ne.kt]=1;
    q.push(ne);
    if(ne.kt==ed.kt)
    {
    printf("%d\n",q.back().ans);
    for(int k=1;k<=q.back().ans;k++) printf("%c",q.back().bz[k]+'A'-1);
    exit(0);
    }
    }
    }
    q.pop();
    
    }
    printf("0");
    
    }
    

    最后

    我是在网课期间摸鱼写作的,很辛苦。给个红心不过分吧。。。

    • 1

    信息

    ID
    1331
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    (无)
    递交数
    3
    已通过
    2
    上传者