UVa 704 - Colour Hash

題目:如題目給出的圖形(下面給出),可以執行四種操作:左邊的圓形順時針旋轉,右邊的圓形順時針旋轉,

            左邊的圓形逆時針旋轉,右邊的圓形逆時針旋轉;問嫩否從給定狀態在16步內走到初始狀態(如下圖)。

             

分析:圖論,搜索,雙向廣搜。這裡使用雙向bfs求解,利用map判重即可。

            如果使用bfs結果會很大導致TLE和MLE;

            首先,利用已知狀態,搜索八層(兩萬多個節點),將結果存到隊列和map中; 

            然後,利用最終狀態反向搜索,如果超過八層,沒有發現相遇的節點,即不可能超過;

                        如果發現存在第一次搜索的結果,則找到答案(本次的結果要逆向輸出)。

說明:注意輸出最小的數字串(同一個方向旋轉三次和反向轉三次等價)。

#include <iostream>  
#include <cstring>  
#include <string> 
#include <queue>
#include <map>

using namespace std;

int ans[21] = {0, 3, 4, 3, 0, 5, 6, 5, 0, 1, 2, 1, 0, 7, 8, 7, 0, 9, 10, 9, 0};
int match(int string1[], int string2[])
{
    for (int i = 0; i < 21; ++ i) {
        if (string1[i] != string2[i]) {
            return false;
        }
    }
    return true;
}

int  rotation_buf[21];
int  rotation_maps[4][21] = {
    2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    0, 1, 2, 3, 4, 5, 6, 7, 8, 19, 20, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
    10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 15, 16, 17, 18, 19, 20,  
    0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 9, 10};

void wheel_rotation(int id, int data[])
{
    for (int i = 0; i < 21; ++ i) {
        rotation_buf[i] = data[i];
    }
    for (int i = 0; i < 21; ++ i) {
        data[rotation_maps[id][i]] = rotation_buf[i];
    }
}

class qnode
{
public:
    int  steps;
    char state[22];
    char operate[10];
    qnode(){}
    qnode(int data[], int Steps) {
        steps = Steps;
        for (int i = 0; i < 21; ++ i) {
            state[i] = data[i]+'0';
        }
        state[21] = 0;
        for (int i = 0; i < 10; ++ i) {
            operate[i] = 0;
        }
    }
};

qnode Q1[30000];
map<string, int> M1;
int bfs1(int data[], int ans[])
{
    M1.clear();
    int move = 1, save = 1;
    qnode now(data, 0);
    M1[now.state] = save;
    Q1[save ++] = now;
    while (move < save) {
        now = Q1[move ++];
        if (now.steps > 8) {
            return 0;
        }
        for (int i = 0; i < 4; ++ i) {
            for (int j = 0; j < 21; ++ j) {
                data[j] = now.state[j]-'0';
            }
            wheel_rotation(i, data);
            qnode New(data, now.steps+1);
            if (!M1[New.state]) {
                M1[New.state] = save;
                strcpy(New.operate, now.operate);
                New.operate[now.steps] = i+'1';
                Q1[save ++] = New;
                if (match(data, ans)) {
                    puts(New.operate);
                    return 1;
                }
            }
        }
    }
    return 0;
}

qnode Q2[30000];
map<string, int> M2;
int bfs2(int ans[])
{
    int data[21], id[4] = {2, 3, 0, 1};// 要求數字串最小 
    for (int i = 0; i < 21; ++ i) {
        data[i] = ans[i];
    }
    M2.clear();
    int move = 1, save = 1;
    qnode now(data, 0);
    M2[now.state] = save;
    Q2[save ++] = now;
    while (move < save) {
        now = Q2[move ++];
        if (M1[now.state]) {
            printf("%s",Q1[M1[now.state]].operate);
            for (int i = now.steps-1; i >= 0; -- i) {
                printf("%c",now.operate[i]);
            }
            puts("");
            return 1;
        }
        if (now.steps > 8) {
            return 0;
        }
        for (int i = 0; i < 4; ++ i) {
            for (int j = 0; j < 21; ++ j) {
                data[j] = now.state[j]-'0';
            }
            wheel_rotation(id[i], data);
            qnode New(data, now.steps+1);
            if (!M2[New.state]) {
                M2[New.state] = save;
                strcpy(New.operate, now.operate);
                if (id[i] < 2) {
                    New.operate[now.steps] = id[i]+'3';
                }else {
                    New.operate[now.steps] = id[i]-1+'0';
                }
                Q2[save ++] = New;
            }
        }
    }
    return 0;
}

int main()
{
    int n, input[24];
    scanf("%d",&n);
    while (n --) {
        for (int i = 0; i < 24; ++ i) {
            scanf("%d",&input[i]);
        }
        if (match(input, ans)) {
            puts("PUZZLE ALREADY SOLVED");
        }else if (!bfs1(input, ans) && !bfs2(ans)) {
            puts("NO SOLUTION WAS FOUND IN 16 STEPS");
        }
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值