Swivel game (IDA*)

Insert picture description here

Idea: Seeking the smallest operand. We found that there are 4 choices for each operation. The search tree will be very deep, so search by operand and use IDA*. From the question, we can see that this input and the corresponding subscript are like this,

Insert picture description here

When doing 8 operations, we can find that he will only change the position of one number per operation. Let's find out which of the 8 middle numbers appears the most as res, then our least and most important operand is 8-res , Let him as the valuation function. Because the smallest operand is required, the inverse operation such as first A and then F is equivalent to no change, so we record the inverse operation corresponding to each operation. The subscript corresponds to 0 (A) and the reverse operation is 5 (F). In order to facilitate the movement of numbers, we first write the subscripts to be modified corresponding to the 8 operations.

Insert picture description here

#pragma GCC optimize(2)
#include<bits/stdc++.h>
 
using namespace std;
typedef long long ll;
#define SIS std::ios::sync_with_stdio(false)
#define space putchar(' ')
#define enter putchar('\n')
#define lson root<<1
#define rson root<<1|1
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
const int mod=1e9+7;
const int N=2e5+5;
const int inf=0x7f7f7f7f;

int gcd(int a,int b)
{
    
    
    return b==0?a:gcd(b,a%b);
}
 
ll lcm(ll a,ll b)
{
    
    
    return a*(b/gcd(a,b));
}
 
template <class T>
void read(T &x)
{
    
    
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-')
            op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op)
        x = -x;
}
template <class T>
void write(T x)
{
    
    
    if(x < 0)
        x = -x, putchar('-');
    if(x >= 10)
         write(x / 10);
    putchar('0' + x % 10);
}
ll qsm(int a,int b,int p)
{
    
    
    ll res=1%p;
    while(b)
    {
    
    
        if(b&1)
            res=res*a%p;
        a=1ll*a*a%p;
        b>>=1;
    }
    return res;
}
int mp[8][7]={
    
    
    {
    
    0,2,6,11,15,20,22},
    {
    
    1,3,8,12,17,21,23},
    {
    
    10,9,8,7,6,5,4},
    {
    
    19,18,17,16,15,14,13},
    {
    
    23,21,17,12,8,3,1},
    {
    
    22,20,15,11,6,2,0},
    {
    
    13,14,15,16,17,18,19},
    {
    
    4,5,6,7,8,9,10}

};//操作对应修改的地方
int opposite[8]={
    
    5,4,7,6,1,0,3,2};//对应的逆操作
int center[8]={
    
    6,7,8,12,17,16,15,11};//中间8个数
int a[100],path[100];
int f()
{
    
    
    int sum[4]={
    
    0};
    for(int i=0;i<8;i++) sum[a[center[i]]]++;
    int res=0;
    for(int i=1;i<=3;i++)
    {
    
    
        res=max(res,sum[i]);
    }
    return 8-res;


}
void move(int x)
{
    
    
    int t=a[mp[x][0]];
    for(int i=0;i<6;i++) a[mp[x][i]]=a[mp[x][i+1]];
    a[mp[x][6]]=t;
}
bool dfs(int u,int mxdep,int last)
{
    
    
    if(u+f()>mxdep)return false;
    if(f()==0)return true;
    for(int i=0;i<8;i++)
    {
    
    
        if(opposite[i]!=last)
        {
    
    
            move(i);
            path[u]=i;
            if(dfs(u+1,mxdep,i))return true;
            move(opposite[i]);
        }
    }
    return false;
}

int main()
{
    
    
   
   while(cin>>a[0],a[0])
   {
    
    
       for(int i=1;i<24;i++)cin>>a[i];
       int dep=0;
       while(!dfs(0,dep,-1))dep++;
       if(!dep) printf("No moves needed");
       else {
    
    
           for(int i=0;i<dep;i++)printf("%c",path[i]+'A');

       }
       printf("\n%d\n",a[6]);

   }

   
   return 0;

}


Guess you like

Origin blog.csdn.net/qq_43619680/article/details/112628436