The Rotation Game POJ-2286(迭代加深搜索)

题意:对一个#字行图案的格子上填上1,2,3数字,可以进行A-H八种变化,使邻近#字中心空格的8个数字都相同,求字典序最小的方案。

分析:首先该题需要剪枝,不然会超时,可以将估价函数设为中心最少还有几个数字不相同(h(x)<=h*(x)),然后就是状态的表示,可以直接采用题目所给的数字序列,然后操作时建立一个操作的映射表进行操作(本来想建立一个链表表示#字,看来下别人的确实发现没必要)。

 

#include <cstdio>
#include <iostream>
#include <cstring>

using namespace std;

int rot[10][10]={                //操作打表
    {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
    {23,21,17,12,8,3,1},        //E
    {22,20,15,11,6,2,0},         //F
    {13,14,15,16,17,18,19},     //G
    {4,5,6,7,8,9,10}             //H
};
int cent[10]={6,7,8,11,12,15,16,17}; //中间8个位置

int a[30],maxh;
char put[100001];

bool check()
{
    for(int i=1;i<8;i++)
        if(a[cent[i]]!=a[cent[0]]) return false;

    return true;
}

int dis()
{
    int cnt=0,mi=100010;
    for(int i=1;i<=3;i++)
    {
        cnt=0;
        for(int j=0;j<8;j++)
        {
            if(a[cent[j]]!=i) cnt++;
        }
        mi=min(mi,cnt);
    }
    return mi;
}

void mov(int x)
{
    int t=a[rot[x][0]];
    for(int i=0;i<6;i++) a[rot[x][i]]=a[rot[x][i+1]];
    a[rot[x][6]]=t;
}
int dfs(int h)
{
    if(h>maxh) return 0;
    if(check()){put[h]='\0'; return 1;}
    if(h+dis()>maxh) return 0;

    for(int i=0;i<8;i++)
    {
        put[h]='A'+i;
        mov(i);
        if(dfs(h+1)) return 1;
        if(i%2) mov((i+3)%8);
        else mov((i+5)%8);
    }

    return 0;
}

int main()
{
    while(scanf("%d",a)&&a[0])
    {
        for(int i=1;i<24;i++) scanf("%d",a+i);
        maxh=1;
        if(check()) cout<<"No moves needed"<<'\n'<<a[cent[0]]<<endl;
        else{
        while(!dfs(0)) maxh++;
        printf("%s\n%d\n",put,a[cent[0]]);}
    }
}

 

posted @ 2020-02-04 20:11  Npunchman  阅读(134)  评论(0)    收藏  举报