Sicily 1151. 魔板[Speical judge]

31 篇文章 0 订阅
/*
相对于1150,这一题需要在细节上节省更多时间,包括以下几点:
1、string的处理效率太低,此处使用int数组存储数据,
   也可以直接使用int,但在进行ABC转换时就需要进行乘除法,
   会浪费很多时间,相对来说对数组的操作更快 
   而且重点在于,使用数组时对ABC操作的修改更为方便 
2、使用康拓展开进行哈希操作,构建哈希表进行快速查询 
*/
/*
Run Time: 0.21secs
Run Memory: 940KB
*/

#include <iostream>
#include <string>
#include <memory.h>     //memset初始化 
#include <set>
#include <queue>

using namespace std;

typedef struct Node{
    int node[8]; 
    string parents;
};

int N;          //要求步数 
int dest[8];    //目标状态 
int source[] = {1, 2, 3, 4, 8, 7, 6, 5};  //初始状态 
int cantorNum[] = {5040, 720, 120, 24, 6, 2, 1, 1};   //长为n的序列的康拓展开需要用到的数:7!,6!...1!,0! 

int cantor(const Node& theNode){
    int result = 0; 
    for(int i=0; i<8; i++){
        int num = 0;
        for(int j=i+1; j<8; j++){
            if(theNode.node[j] < theNode.node[i]){
                num++;
            }
        }
        result += num * cantorNum[i];
    }
    return result;
}

bool isSame(int a[8], int b[8]){
    for(int i=0; i<8; i++)
        if(a[i] != b[i])
            return false;
    return true;
} 

//A:上下行互换
Node A(const Node& inputNode){
    Node newOne;
    newOne.node[0] = inputNode.node[4];
    newOne.node[1] = inputNode.node[5];
    newOne.node[2] = inputNode.node[6];
    newOne.node[3] = inputNode.node[7];
    newOne.node[4] = inputNode.node[0];
    newOne.node[5] = inputNode.node[1];
    newOne.node[6] = inputNode.node[2];
    newOne.node[7] = inputNode.node[3];
    
    newOne.parents = inputNode.parents + "A";
  
    return newOne;
}

//B:每次以行循环右移一个
Node B(const Node& inputNode){
    Node newOne;
    newOne.node[0] = inputNode.node[3];
    newOne.node[1] = inputNode.node[0];
    newOne.node[2] = inputNode.node[1];
    newOne.node[3] = inputNode.node[2];
    newOne.node[4] = inputNode.node[7];
    newOne.node[5] = inputNode.node[4];
    newOne.node[6] = inputNode.node[5];
    newOne.node[7] = inputNode.node[6];
    
    newOne.parents = inputNode.parents + "B";
  
    return newOne;
}

//C:中间四小块顺时针转一格
Node C(const Node& inputNode){
    Node newOne;
    newOne.node[0] = inputNode.node[0];
    newOne.node[1] = inputNode.node[5];
    newOne.node[2] = inputNode.node[1];
    newOne.node[3] = inputNode.node[3];
    newOne.node[4] = inputNode.node[4];
    newOne.node[5] = inputNode.node[6];
    newOne.node[6] = inputNode.node[2];
    newOne.node[7] = inputNode.node[7];
    
    newOne.parents = inputNode.parents + "C";
  
    return newOne;
}

Node find(Node sourceNode){
    queue<Node> nodeQueue; //节点队列 
    int used[50000];       //使用过的状态 
    memset(used, 0, sizeof(used));
    
    if(isSame(sourceNode.node, dest))
        return sourceNode; 
    nodeQueue.push(sourceNode);
    used[cantor(sourceNode)] = 1;

    while(!nodeQueue.empty()){
        Node theNode = nodeQueue.front();    //获取队列头                 
        nodeQueue.pop();
        
        if(theNode.parents.length() >= N){    //超出步数时候退出循环 
           break;
        }
        
        Node bufNewNode[3];
        bufNewNode[0] = A(theNode); 
        bufNewNode[1] = B(theNode); 
        bufNewNode[2] = C(theNode); 
        
        for(int i=0; i<3; i++){
            if(isSame(bufNewNode[i].node, dest))    //如果找到了目标,则返回结果 
                return bufNewNode[i];
            
            if(used[cantor(bufNewNode[i])] == 0){  //不是目标则检查其是否已经看过,否则记录的同时放入队列 
                nodeQueue.push(bufNewNode[i]);
                used[cantor(bufNewNode[i])] = 1;
            }
        }
    } 
    Node notFound;
    notFound.parents = "NotFound";
    
    return notFound;
}




int main()
{
    while (cin>>N && (N!=-1)){
        for(int i=0; i<8; i++)
            cin >> dest[i];

        //设定初始状态,传入方法开始执行 
        Node bufNode;
        for(int i=0; i<8; i++)    
            bufNode.node[i] = source[i];
        bufNode.parents = "";
        
        Node destNode = find(bufNode);
        
        if(destNode.parents == "NotFound"){
            cout << "-1" << endl;
        }else{
            cout << destNode.parents.length() << " " << destNode.parents << endl;
        }
    } 
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值