acwing1107魔板

#include<bits/stdc++.h>

using namespace std;

const int N = 10;

char g[2][4];
unordered_map<string, pair<char, string>>pre;  //一个字符串映射到一个操作和一个状态 
unordered_map<string, int>dist;

void Set(string state){  //将二维数组重新赋给字符串  
    for(int i = 0; i < 4; i ++ ) g[0][i] = state[i];
    for(int i = 0, j = 7; i < 4; i ++ , j -- ) g[1][i] = state[j];
}

string get(){    //用于将魔板状态放入临时二维数组g内 
    string res;
    for(int i = 0; i < 4; i ++ ){
        res += g[0][i];  //放第一行 
    }
    for(int i = 3; i >= 0; i -- ) res += g[1][i];   //放第二行
    return res;
}

string move0(string start){  //交换上下两行 
    Set(start); 
    for(int i = 0; i < 4; i ++ ){ 
        swap(g[0][i], g[1][i]);
    }
    return get();
}

string move1(string start){  //将最右边的一列插入到最左边 
    Set(start); 
    char s1 = g[0][3];
    char s2 = g[1][3];
    for(int i = 3; i >= 0; i -- ){
        g[0][i] = g[0][i - 1];
        g[1][i] = g[1][i - 1];
    }
    g[0][0] = s1;
    g[1][0] = s2;
    return get();
}

string move2(string start){  //将中间四个数顺时针旋转 
    Set(start);
    char s = g[0][1];
    g[0][1] = g[1][1];
    g[1][1] = g[1][2];
    g[1][2] = g[0][2];
    g[0][2] = s;
    return get();

int bfs(string start, string end){
    if(start == end) return 0;
    
    queue<string>q;
    q.push(start);  //把这种初始魔板字符串状态放入队列
    dist[start] = 0;  //记录到达这个状态的步数为0 
    
    while(!q.empty()){
        auto op = q.front();  //从队列中取出 
        q.pop();
        
        string m[3];
        //按照规则进行三种状态变化
        m[0] = move0(op);
        m[1] = move1(op);
        m[2] = move2(op);
        
        for(int i = 0; i < 3; i ++ ){
            if(!dist.count(m[i])){  //这一步很关键,count就是查找在优先队列中m[i]的数量 
            //如果这种状态没有出现过 
                dist[m[i]] = dist[op] + 1;  //记录步数 
                pre[m[i]] = {'A' + i, op};
                q.push(m[i]); 
                if(end == m[i]) return dist[m[i]];
            }
        }
    }
    return -1;
}

int main()
{
    int x;
    string start, end;
    for(int i = 0; i < 8; i ++ ){
        cin>>x;
        end += char(x + '0');  //end是以字符串形式记录的初始魔板序列
    }
    
    for(int i = 1; i <= 8; i ++ ) start += char(i + '0');  //start是记录的基本状态的魔板序列 
    
    int step = bfs(start, end);  //宽搜得到最短序列长度
    
    cout<<step<<endl;
    
    string res;  //res是用于记录的空字符串
            
    while(end != start){  //当魔板状态不是初始状态时
        res += pre[end].first;  //pre.first记录的是上一步的操作 
        end = pre[end].second;  //pre.second记录的是上一步的状态
    }
    reverse(res.begin(), res.end());
    //因为记录命令序列的时候是从理想状态倒推出的初始状态,所以输出时要对命令字符串逆序 
    if(step > 0) cout<<res<<endl;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值