Uva1343 The Rotation Game 【IDA*】【例题7-12】

来源:互联网 发布:淘宝上九块九包邮 编辑:程序博客网 时间:2024/06/05 02:46

题目:The Rotation Game

题意:给出一个形状(原题有图)的棋盘上分别有8123,要往AH方向旋转棋盘,使中间8个方格数字相同。

有8个移动方向,朝向哪个方向移动就是对应的整条都向本方向移动一格,第一位补到最后一位。输出最少的移动方向序列,并输出中间数字为几。

思路:看了紫书的分析后并没有思路。。。最后还是看了代码库的IDA*求解的

(1)画图:将8个方向的的数字在输入的一维数组对应下标的位置分别存放到二维数组中,只需写出ABCD,EFGH是ABCD的反方向;

(2)枚举深度进行dfs;

(3)dfs搜索:枚举8个方向,将当前方向保存到一个结果数组中,枚举到某个方向后,在这个方向的数字进行移动,然后继续递归,每次递归后需将改变的回溯,利用反方向再次移动即可。直到找到后输出移动方向序列即可;

(4)剪枝:看下估值函数h():计算当前中间数字相同最多即不同最少的一个值;然后判断当前深度d + h() 是否小于 枚举深度maxd  ,小于的话说明可以再maxd下得出结果,否则都大于maxd了,再搜索也不可能找到,直接剪枝掉!

参考:紫书代码仓库

代码:

#include <iostream>#include <cstdio>#include <algorithm>using namespace std;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}; //分别表示F E H G B A D Cconst int center[8] = {6, 7, 8, 11, 12, 15, 16, 17};//中间位置int a[24];char ans[1000];bool is_fin(){//是否达到目标状态    for(int i=0;i<8;i++)        if(a[center[0]] != a[center[i]]) return false;    return true;}int diff(int target){//计算当前差几个达到目标    int cot = 0;    for(int i=0;i<8;i++)        if(a[center[i]] != target) cot++;    return cot;}void moved(int i){//向i方向移动    int temp = a[line[i][0]];    for(int j=0;j<6;j++) a[line[i][j]] = a[line[i][j+1]];    a[line[i][6]] = temp;}int h(){//估值函数    return min(min(diff(1),diff(2)),diff(3));}bool dfs(int d,int maxd){    if(is_fin()){//达到目标        ans[d] = '\0';        printf("%s\n",ans);        return true;    }    if(d + h() > maxd) return false;//剪枝    for(int i=0;i<8;i++){        ans[d] = i + 'A';        moved(i);//向i方向移动        if(dfs(d+1,maxd)) return true;        moved(rev[i]);//还原,回溯    }    return false;}void solve(){    for(int maxd=1; ;maxd++)        if(dfs(0,maxd)) break;}void init(){    for(int i=4;i<8;i++)//EFGH由ABCD得出        for(int j=0;j<7;j++) line[i][j] = line[rev[i]][6-j];}int main(){    init();    while(scanf("%d",&a[0]) == 1 && a[0]){        for(int i=1;i<24;i++) scanf("%d",&a[i]);        if(is_fin()) printf("No moves needed\n");        else solve();        printf("%d\n",a[6]);//最终中间的数字    }    return 0;}


0 0
原创粉丝点击