hdu 1667 The Rotation Game(IDA*)

4 篇文章 0 订阅
1 篇文章 0 订阅

题目大意:

        有一个井字形结构的图形,每条线上7个数字(1,2,3,),每次可以从八个方向将一条线上的数字循环移动1个距离,问经过最少几次什么操作,可以将图形中间的八个方块变成同一种数字。

解题思路:

        使用IDA*进行搜索,估价函数为中间八个方块中,不是最多的数字的个数和。

注意点:

        题目的输入和存储都不直观,需要十分细心。

代码:

#include <iostream>

using namespace std;

int line1[7],line2[7],row1[7],row2[7];
int step,ans[10000];
bool flag;

//输入
bool input(){
    int i;
    cin >> row1[0];
    if(row1[0] == 0) return false;
    cin >> row2[0];
    cin >> row1[1] >> row2[1];
    for(i = 0; i < 7; i++){
       cin >> line1[i];
    }
    row1[2] = line1[2];
    row2[2] = line1[4];
    cin >> row1[3] >> row2[3];
    for(i = 0; i < 7; i++){
       cin >> line2[i];
    }
    row1[4] = line2[2];
    row2[4] = line2[4];
    cin >> row1[5] >> row2[5];
    cin >> row1[6] >> row2[6];
    return true;
}

//循环移动
void circle(int a[7],int direction){
    int i,temp;
    if(direction == -1){
        temp = a[0];
        for(i = 1; i < 7; i ++) a[i-1] = a[i];
        a[6] = temp;
    }
    else{
        temp = a[6];
        for(i = 6; i > 0; i --) a[i] = a[i-1];
        a[0] = temp;
    }
    return;
}

//移动
void moveDirec(int direction){
    if(direction == 0){//A操作
        circle(row1,-1);
        line1[2] = row1[2];
        line2[2] = row1[4];
        return;
    }
    if(direction == 1){//B操作
        circle(row2,-1);
        line1[4] = row2[2];
        line2[4] = row2[4];
        return;
    }
    if(direction == 2){//C操作
        circle(line1,1);
        row1[2] = line1[2];
        row2[2] = line1[4];
        return;
    }
    if(direction == 3){//D操作
        circle(line2,1);
        row1[4] = line2[2];
        row2[4] = line2[4];
        return;
    }
    if(direction == 4){//E操作
        circle(row2,1);
        line1[4] = row2[2];
        line2[4] = row2[4];
        return;
    }
    if(direction == 5){//F操作
        circle(row1,1);
        line1[2] = row1[2];
        line2[2] = row1[4];
        return;
    }
    if(direction == 6){//G操作
        circle(line2,-1);
        row1[4] = line2[2];
        row2[4] = line2[4];
        return;
    }
    if(direction == 7){//H操作
        circle(line1,-1);
        row1[2] = line1[2];
        row2[2] = line1[4];
        return;
    }
}

//反移动
void moveBack(int direction){
     if(direction == 0) moveDirec(5);
     if(direction == 1) moveDirec(4);
     if(direction == 2) moveDirec(7);
     if(direction == 3) moveDirec(6);
     if(direction == 4) moveDirec(1);
     if(direction == 5) moveDirec(0);
     if(direction == 6) moveDirec(3);
     if(direction == 7) moveDirec(2);
}
//计算中间数字的种类等
int countKind(int &maxBlock,int &blockNum){
     int i,num[4] = {0},k = 1,kind = 0;
     for(i = 2; i <= 4; i++){
        num[line1[i]] ++;
     }
     num[row1[3]] ++;
     num[row2[3]] ++;
     for(i = 2; i <= 4; i++){
        num[line2[i]] ++;
     }
     if(num[1] != 0) kind ++;
     if(num[2] != 0) kind ++;
     if(num[3] != 0) kind ++;
     if(num[k] < num[2]) k = 2;
     if(num[k] < num[3]) k = 3;
     maxBlock = k;
     blockNum = num[k];
     return kind;
}

int block;

void dfs(int floor){
    int i,kind,maxBlock,blockNum;
    kind = countKind(maxBlock,blockNum);
    if(kind == 1){
       block = maxBlock;
       flag = true;
       return;
    }
    if(floor >= step) return;
    if(floor + (8 - blockNum) > step) return;
     for(i = 0; i < 8; i++){
        moveDirec(i);
        ans[floor] = i;
        dfs(floor + 1);
        moveBack(i);
        if(flag == true) return;
     }
     return;
}

int main()
{
    int maxBlock,blockNum;
    while(input()){
        if(countKind(maxBlock,blockNum) == 1){
            cout << "No moves needed" << endl;
            cout << maxBlock << endl;
            continue;
        }

        step = 0;
        flag = false;
        while(flag == false){
            step ++;
            dfs(0);
        }
        char ch;
        for(int i = 0; i < step; i++){
            ch = 'A' + ans[i];
            cout << ch;
        }
        cout << endl;
        cout << block << endl;
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值