IDA*算法实质就是迭代加深搜索和A*算法的结合,通过迭代加深搜索来寻找答案,借由预估函数h()来进行估计与剪枝。

本题主框架如下:

else for(int maxd=1;;maxd++)
        {
            if(dfs(0,maxd)) break;
        }

由1开始不断加深最大深度,如果当前深度+需要到达目标的步数>最大深度时,则剪枝,需要达到目标的步数可以用函数h()表示,其返回值和计算方法由具体问题确定,本题中则是中间8个格子中最少的不同数字量。

具体代码如下:

///输入数字对应的位置
/*
      00    01
      02    03
04 05 06 07 08 09 10
      11    12
13 14 15 16 17 18 19
      20    21
      22    23
*/
#include<cstdio>
#include<algorithm>
using namespace std;

const int rev[8] = {5, 4, 7, 6, 1, 0, 3, 2};///每个行对应的逆行
const int center[8]={6,7,8,11,12,15,16,17};
int a[24];///输入
///每行对应的数字在数组a中的下标
int line[8][7]=
{
    { 0, 2, 6,11,15,20,22}, // A
    { 1, 3, 8,12,17,21,23}, // B
    {10, 9, 8, 7, 6, 5, 4}, // C
    {19,18,17,16,15,14,13}, // D
};
char ans[1000];///答案数组,存储所走步数

bool is_final()///判断是否达到题目符合条件
{
    for(int i=1;i<8;i++)
        if(a[center[i]]!=a[center[0]]) return false;
        return true;
}

int diff(int target)///查找不同数字的数量
{
    int ans=0;
    for(int i = 0; i < 8; i++)
        if(a[center[i]] != target) ans++;
    return ans;
}

inline int h()///求最少还需要几步达到目标条件
{
    return min(min(diff(1), diff(2)), diff(3));
}

inline void move(int i)///对相应方向进行题目中的旋转操作
{
    int tmp = a[line[i][0]];
    for(int j = 0; j < 6; j++) a[line[i][j]] = a[line[i][j+1]];
    a[line[i][6]] = tmp;
}

bool dfs(int d,int maxd)///迭代搜索
{
    if(is_final())
    {
        ans[d]='\0';
        printf("%s\n",ans);
        return true;
    }
    if(d+h()>maxd) return false;///剪枝
    for(int i=0;i<8;i++)///对每个方向进行旋转
    {
        ans[d]='A'+i;
        move(i);
        if(dfs(d+1,maxd)) return true;
        move(rev[i]);///如果递归失败,调整回原来模式
    }
    return false;
}

int main()
{
    for(int i = 4; i < 8; i++)
        for(int j = 0; j < 7; j++) line[i][j] = line[rev[i]][6-j];///将对应方向的数字调整好
    while(~scanf("%d",&a[0])&&a[0])
    {
        for(int i=1; i<24; i++)
        {
            scanf("%d",&a[i]);
        if(!a[i]) return 0;
        }
        if(is_final()) printf("No moves needed\n");
        else for(int maxd=1;;maxd++)
        {
            if(dfs(0,maxd)) break;
        }
        printf("%d\n",a[6]);
    }
    return 0;
}