hdu1667 The Rotation Game

题目描述:
你有一个#。有8个不同方向可以动,编号依次为A-H。求使其中心8个块数字变成相同时,最短字典序最小的字符串以及中心的数字。

题解:

对于这种状态极为发散的搜索,我们可使用A*。而这道题要求最短,我们可以采用IDA*。

估价函数h=8-(中心块上出现最多的数的出现次数)。

因为每动一次只踢出去一个格,拉进来一个格。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int rnd[10][10]={{},{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}};
struct jr
{
    int a[25];
    int ans[25],g;
    int h()
    {
        int cnt[4]={0,0,0,0};
        cnt[a[7]]++,cnt[a[8]]++,cnt[a[9]]++;
        cnt[a[12]]++,cnt[a[13]]++;
        cnt[a[16]]++,cnt[a[17]]++,cnt[a[18]]++;
        return 8-max(cnt[1],max(cnt[2],cnt[3]));
    }
    void trn(int k)
    {
        for(int i=1;i<=6;i++)
            swap(a[rnd[k][i-1]],a[rnd[k][i]]);
    }
}j0;
int lim;
bool fg;
void dfs(jr u)
{
    int hh = u.h();
    if(!hh)
    {
        for(int i=1;i<=u.g;i++)printf("%c",'A'+u.ans[i]-1);
        printf("\n%d\n",u.a[7]);
        fg=1;
        return ;
    }
    if(u.g+hh>lim)return ;
    if(fg)return ;
    jr tmp;
    for(int k=1;k<=8;k++)
    {
        tmp = u;
        tmp.ans[++tmp.g]=k;
        tmp.trn(k);
        dfs(tmp);
    }
}
int main()
{
    while(scanf("%d",&j0.a[1])&&scanf("%d",&j0.a[2])>0)
    {
        for(int i=3;i<=24;i++)scanf("%d",&j0.a[i]);
        j0.g=0;
        if(j0.h()==0)
        {
            printf("No moves needed\n%d\n",j0.a[7]);
            continue;
        }
        for(lim=1,fg=0;!fg;lim++)
        {
            dfs(j0);
        }
    }
    return 0;
}

 

posted @ 2018-11-24 07:45  LiGuanlin  阅读(114)  评论(0编辑  收藏  举报