B30 IDA*算法 The Rotation Game

视频链接:131 IDA*算法 The Rotation Game_哔哩哔哩_bilibili

POJ2286 The Rotation Game

 

 

 

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

int op[8][7]={ //8个操作的格子编号
    {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[8]={6,7,8,11,12,15,16,17}; //中心
int iop[8]={5,4,7,6,1,0,3,2}; //逆操作
int dep,a[24],path[100];

void operate(int x){ //第x种操作
  int t=a[op[x][0]];
  for(int i=0; i<6; i++)
    a[op[x][i]]=a[op[x][i+1]];
  a[op[x][6]]=t;
}
bool check(){ //中心数字是否相同
  for(int i=1; i<8; i++)
    if(a[cent[i]]!=a[cent[0]]) return false;
  return true; 
}
int f(){ //估价函数: f=8-k
  static int cnt[4]; memset(cnt,0,sizeof cnt);
  for(int i=0; i<8; i++) cnt[a[cent[i]]]++;
  int k=0; //中心数字最多的出现次数为k
  for(int i=1; i<=3; i++) k=max(k,cnt[i]);
  return 8-k; //换掉不同数字,至少操作8-k次
}
//第u层, 上一次操作为last
bool dfs(int u,int last){
  if(u+f()>dep) return false;
  if(check()) return true;
  for(int i=0; i<8; i++){
    if(iop[i]==last) continue;
    operate(i);      //操作一次
    path[u]=i;
    if(dfs(u+1,i)) return true;
    operate(iop[i]); //恢复现场
  }
  return false;
}
int main(){
  while(scanf("%d",&a[0]),a[0]){
    for(int i=1;i<24;i++)scanf("%d",&a[i]);
    for(dep=0; !dfs(0,-1); dep++);
    if(!dep) printf("No moves needed");
    for(int i=0; i<dep; i++) 
      printf("%c",'A'+path[i]);
    printf("\n%d\n",a[6]);
  }
}

 

posted @ 2023-06-25 12:14  董晓  阅读(160)  评论(0编辑  收藏  举报