蓝桥杯 历届试题 九宫重排 搜索+康托展开

问题描述

  如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。

  我们把第一个图的局面记为:12345678.
  把第二个图的局面记为:123.46758
  显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
  本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。

输入格式

  输入第一行包含九宫的初态,第二行包含九宫的终态。

输出格式

  输出最少的步数,如果不存在方案,则输出-1。

样例输入

12345678.
123.46758

样例输出

3

样例输入

13524678.
46758123.

样例输出

22

思路:

bfs,通过康拓展开来标记出现的状态。

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
const int maxn=362885;
char s[15];
char e[15];
int vis[maxn];
int fin;
int a[15];
int b[15];
int fn[10];
int pos[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int px,py;
struct node
{
    int a[15];
    int px,py;
    int step;
};
int can (int x[])
{
    int ans=0;
    for (int i=0;i<9;i++)
    {
        int num=0;
        for (int j=i+1;j<9;j++)
        {
            if(x[i]>x[j]) num++;
        }
        ans+=fn[9-i-1]*num;
    }
    return ans;
}
int bfs ()
{
    node now,next;
    queue<node>q;
    memcpy(now.a,a,sizeof(now.a));
    now.px=px; now.py=py;
    vis[can(now.a)]=1;
    now.step=0;
    q.push(now);
    while(!q.empty())
    {
        now=q.front();
        q.pop();
        int t=can(now.a);
        if(t==fin) return now.step;
        for (int i=0;i<4;i++)
        {
            next=now;
            next.step++;
            int tx=now.px+pos[i][0];
            int ty=now.py+pos[i][1];
            if(tx<0||tx>=3||ty<0||ty>=3) continue;
            swap(next.a[tx*3+ty],next.a[next.px*3+next.py]);
            int t=can(next.a);
            if(!vis[t])
            {
                next.px=tx;
                next.py=ty;
                vis[t]=1;
                q.push(next);
            }
        }
    }
    return -1;
}
int main()
{
    fn[0]=1;
    for (int i=1;i<=9;i++) fn[i]=fn[i-1]*i;
    memset (vis,0,sizeof(vis));
    scanf("%s",s);
    scanf("%s",e);
    int len=strlen(s);
    for (int i=0;i<len;i++)
    {
        if(s[i]=='.') {a[i]=9; px=i/3,py=i%3;}
        else a[i]=s[i]-'0';
    }
    for (int i=0;i<len;i++)
    {
        if(e[i]=='.') b[i]=9;
        else b[i]=e[i]-'0';
    }
    fin=can(b);
    printf("%d\n",bfs());
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41410799/article/details/88553936