UVA 1343 The Rotation Game IDA*

使用IDA*的思想解题, 主要的难点在于如何模拟Rotate操作,以及在检查终点和启发函数时检测中心的8个方格数字是否相同

#include <cstdio>
#include <algorithm>
using namespace std;
/*  方格编号
      00    01
      02    03
04 05 06 07 08 09 10
      11    12
13 14 15 16 17 18 19
      20    21
      22    23
*/

// lines E~H are computed with the help of rev[]
int line[8][7]={
  { 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
};

const int rev[8] = {5, 4, 7, 6, 1, 0, 3, 2}; // 每个line对应的reverse line

// center squares
const int center[8] = {6, 7, 8, 11, 12, 15, 16, 17};

int a[24];
char ans[1000];

bool is_final(){
    for(int i=0;i<8;i++){
        if(a[center[i]]!=a[center[0]]) return false;
    }
    return true;
}

int diff(int target){
    int dif=0;
    for(int i=0;i<8;i++){
        if(a[center[i]]!=target) dif++;
    }
    return dif;
}

inline int h(){ //估价函数计算1,2,3结果中距离最小的一个距离
    return min(min(diff(1),diff(2)),diff(3));
}

inline void mov(int i){
    int tmp=a[line[i][0]];
    for(int j=0;j<6;j++) a[line[i][j]]=a[line[i][j+1]];
    a[line[i][6]]=tmp;
}

bool dfs(int d,int maxd){ //IDA*dfs保证第一个搜到的答案是步数最小且路径字典序最小
    if(is_final()){
        ans[d]='\0';
        printf("%s\n",ans);
        return true;
    }
    if(d+h()>maxd) return false; //已走+估价>最大深度则回溯
    for(int i=0;i<8;i++){
        ans[d]='A'+i;
        mov(i);
        if(dfs(d+1,maxd)) return true;
        mov(rev[i]);    //完成对该结点子节点的搜索后还原mov操作
    }
    return false;
}

int main (){
    //freopen("datain.txt","r",stdin);
    for(int i = 4; i < 8; i++)
        for(int j = 0; j < 7; j++) line[i][j] = line[rev[i]][6-j];

    while(scanf("%d",&a[0])==1&&a[0]){
        for(int i=1;i<24;i++) scanf("%d",&a[i]);
        if(is_final()){
            puts("No moves needed");
        } else {
            for(int maxd=1;;maxd++) if(dfs(0,maxd))break; //ID
        }
        printf("%d\n",a[6]);
  }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值