hdu 1667 The Rotation Game(IDA*)

題目大意:

        有一個井字形結構的圖形,每條線上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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章