IDA-star深搜+模拟标记法+剪枝

题目:回转游戏

Code:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int ti;//times 次数(IDA star)
int g[100];
int odr[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}
};//把图中的点依次标记为1-24,所得到的,ABCDEFGH分别对应的操作序列
int cir[8]={7,8,9,13,18,17,16,12};//中间8个数的序列
int price(){//估价函数
    int c1=0,c2=0,c3=0;
    for(int i=0;i<8;i++)
        if(g[cir[i]]==1)c1++;
        else if(g[cir[i]]==2)c2++;
        else c3++;
    int ma=max(max(c1,c2),c3);
    return (8-ma);
}
bool check(){//判断当前是否已经满足题意
    for(int i=0;i<7;i++)
        if(g[cir[i]]!=g[cir[i+1]])
            return false;
    return true;
}
void move(int i){//操作函数
    int tmp=g[odr[i][0]];
    for(int j=1;j<7;j++){
        g[odr[i][j-1]]=g[odr[i][j]];
    }
    g[odr[i][6]]=tmp;
}
int oppo[8]={5,4,7,6,1,0,3,2};//剪枝用,成对操作
bool dfs(int u,int last,string res){//深搜过程
    if(u+price()>ti)return false;
    if(check()){
        cout<<res<<endl;
        cout<<g[7]<<endl;
        return true;}
    for(int i=0;i<8;i++){
        if(oppo[i]==last)continue;
        move(i);
        if(dfs(u+1,i,res+(char)('A'+i)))return true;
        move(oppo[i]);
    }
    return false;
}
int main(){
    while(cin>>g[1]){
        ti=0;
        if(g[1]==0)break;
        for(int i=2;i<=24;i++)cin>>g[i];
        if(check()){
            puts("No moves needed");
            cout<<g[7]<<endl;
        }
        else 
            while(true){
            ++ti;
            if(dfs(0,-1,""))break;
        }

    }
}

一遍写对我真实太开心了hh