hdu 1667 The Rotation Game ( IDA* )

题目大意:

给你一个“井”子状的board,对称的由24个方块组成,每个方块上有123三个数字中的一个。给你初始状态,共有八种变换方式,求字典序最小的最短的的变换路径使得,board中间的八个方块上数字相同。(建议看下题目中的图就懂啦)。

IDA*搜索。

我是干脆用结构体保存搜索状态(当然这样很占空间了,可能也耗时间,不过这题15s/150M的时空限制我也是醉了)。保存一个board temp,一个搜索路径path,搜索深度n,以及一个内置的估值函数h()。h()返回的是8减这八个方块上出现最多的数字的次数,因为一次变换只能改变一个数字的个数,所以h()是比实际小的,满足A*条件。接下来就是迭代dfs搜索了。设置一个初值为0的max,当h()时,表示搜到目标,打印然后return true;若n+h()<=max(这其实就是A*的剪枝思想了),往下向八个方向搜索(用数组dir保存)。若有一个方向成功,则return true;都没成功返回false。max反复++,直至搜到答案。

个人觉得ida*比a*的题目要好写呢。。果然dfs比bfs要友善很多啊。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>

using namespace std;

int board[24];
int aim[8]={6,7,8,11,12,15,16,17};
//8个方向,比下标大1
int dir[8][7]= {1,3,7,12,16,21,23,
                2,4,9,13,18,22,24,
                11,10,9,8,7,6,5,
                20,19,18,17,16,15,14,
                24,22,18,13,9,4,2,
                23,21,16,12,7,3,1,
                14,15,16,17,18,19,20,
                5,6,7,8,9,10,11
               };
char diralpha[9]="ABCDEFGH";

struct tnode
{
    int temp[24];
    string path;
    int n;
    inline int h()
    {
        int a=0,b=0,c=0;
        for(int i=0;i<8;i++)
        {
            if(temp[aim[i]]==1)
                a++;
            else if(temp[aim[i]]==2)
                b++;
            else
                c++;
        }
        return 8-max(a,max(b,c));
    }
};

bool dfs(int mmax,tnode x)
{
    if(x.h()==0)
    {
        if(x.n==0)
            printf("No moves needed
%d
",x.temp[aim[0]]);
        else
            cout<<x.path<<endl<<x.temp[aim[0]]<<endl;
        return true;
    }
    if(x.n+x.h()<=mmax)
    {
        tnode y;
        for(int i=0;i<8;i++)
        {
            y=x;
            y.path+=diralpha[i];
            y.n++;
            for(int j=0;j<7;j++)
                y.temp[dir[i][j]-1]=x.temp[dir[i][(j+1)%7]-1];
            if(dfs(mmax,y))
                return true;
        }
    }
    return false;
}

int main()
{
    while(scanf("%d",board),board[0])
    {
        for(int i=1;i<24;i++)
            scanf("%d",board+i);

        tnode st;
        memcpy(st.temp,board,sizeof(board));
        st.n=0;
        st.path="";
        for(int i=0,flag=false;flag==false;i++)
        {
            flag=dfs(i,st);
        }
    }
    return 0;
}
View Code

PS:某学长想用3进制数判重写,然后MLE了无数发。。(?)所以之后要不要考虑自己也作死一发呢。

PS2:最近没怎么更新博客。。也是比较颓,没有好好学习,好好做题(愧疚)。今天算是好好学习了一天吧。。但愿能够坚持下去。。Keep going and never give up!

原文地址:https://www.cnblogs.com/acboyty/p/9595341.html