网易游戏研发工程师笔试题

题目描述

Q最近被邀请去参加了网易最牛大脑的节目,挑战数字魔方的项目。

 

数字魔方为一个3x3的矩阵,矩阵中的每个数字都是(1…9)中的数字,且数字魔方中的数字可能重复。每4个相邻的数字我们称为1个子魔方,整个数字魔方共有4个子魔方(如下图所示)。每一次操作可以选择对某个子魔方顺时针旋转90度,180度或者270度。每个子魔方可以进行多次操作。

 

对子魔方1进行一次操作,顺时针旋转90度,180度,270度后的状态:


项目的挑战任务是,给定数字魔方的一个初始状态,以及一个目标状态,问最少操作多少次可以使得魔方从初始状态改变为目标状态。

 

Q求助于你,希望你能告诉他完成任务的最少操作次数是多少,或者任务不可能完成。

输入描述:

输入的第一行为一个正整数TT<=20),表示测试数据组数。
接下来有T组数据。每组数据有6行。其中前3行为数字魔方的初始状态,后3行为目标状态。每个数据之后有一个空行。保证魔方中的数字为(1…9)中的数字。

输出描述:

对于每一组数据,输出一行,包含一个整数,为最少操作次数。如果不能完成目标,则输出-1

示例1

输入

2

1 2 3

4 5 6

7 8 9

5 4 1

6 2 3

7 8 9

 

1 2 3

4 5 6

7 8 9

2 5 3

1 4 6

7 8 9

输出

3

1

说明

第一个样例为对子魔方1旋转90度,然后对子魔方2旋转90度,再对子魔方1旋转90度。
第二个样例为对子魔方1旋转270度。

 

 1.思路:

将魔方状态转换成一组字符串,由于字符串长度为9,其可能出现的状态的总数一定(不会超过9的阶乘),因此采用BFS广度优先搜索,并使用哈希表来存储状态(若使用数组来存储状态,则需要自己实现“改进的康拓展开式”);res初始化为-1,若得到答案,则break并返回res,若得不到答案,则返回-1.


2.代码:

#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <queue>
#include <cstring>
#include <unordered_map>
using namespace std;
int movx[4]={0,1,3,4};
int fac[9]={1,1,2,6,24,120,720,5040,40320};
bool vis[362890];
//数组索引直接查找,时间复杂度O(1),但需要用康拓展开,自己实现映射过程
//哈希表由红黑树实现,其查找时间复杂度为O(logN)
//C++find函数查找,时间复杂度为O(N);

struct node
{
    string str;
    int step;
};

int str2int(string str)
{
    int cnt[9]={0};
    int res=0;
    int i,j;
    for(i=0;i<9;i++)
        cnt[str[i]-'1']++;
    for(i=0;i<9;i++)
    {
        int x=str[i]-'1';
        int y=0;
        for(j=0;j<x;j++)
            y+=cnt[j];
        res+=y*fac[8-i];
        cnt[x]--;
    }
    return res;
}
string rorate_str_90(string str,int x)
{
    char ch;
    int dx=movx[x];
    ch=str[dx];
    str[dx]=str[dx+3];
    str[dx+3]=str[dx+4];
    str[dx+4]=str[dx+1];
    str[dx+1]=ch;
    return str;
}
string rorate_str_180(string str,int x)
{
    char ch;
    int dx=movx[x];
    ch=str[dx];
    str[dx]=str[dx+4];
    str[dx+4]=ch;
    ch=str[dx+1];
    str[dx+1]=str[dx+3];
    str[dx+3]=ch;
    return str;
}
string rorate_str_270(string str,int x)
{
    char ch;
    int dx=movx[x];
    ch=str[dx];
    str[dx]=str[dx+1];
    str[dx+1]=str[dx+4];
    str[dx+4]=str[dx+3];
    str[dx+3]=ch;
    return str;
}
string calc_str(const vector<int> num)
{
    string str="";
    for(int i=0;i<9;i++)
        str+=('0'+num[i]);
    return str;
}
int main()
{
    int t,i,tmp;
    cin>>t;
    while(t--)
    {
        vector<int> init;
        vector<int> res;
        string init_str,res_str;
        int minx=-1;
        unordered_map<string, int> vis2; //初始化哈希表
//        memset(vis,0,sizeof(vis));
        queue<node> q;
        int num;
        for(i=0;i<9;i++)
        {
            cin>>tmp;
            init.push_back(tmp);
        }
        for(i=0;i<9;i++)
        {
            cin>>tmp;
            res.push_back(tmp);
        }
        init_str=calc_str(init);
        res_str=calc_str(res);
        node init_node;
        init_node.step=0;
        init_node.str=init_str;
        q.push(init_node);
//        vis[str2int(init_node.str)]=true;
        while(!q.empty())
        {
            node tn,nx;
            tn=q.front();q.pop();
            if(tn.str==res_str)
            {
                minx=tn.step;
                break;
            }
            for(i=0;i<4;i++)
            {
                nx.str=rorate_str_90(tn.str,i);
                if(vis2.find(nx.str) == vis2.end()) {
                    vis2[nx.str] = 1;
                    nx.step = tn.step+1;
                    q.push(nx);
                }
//                num=str2int(nx.str);
//                if(!vis[num])
//                {
//                    vis[num]=1;
//                    nx.step=tn.step+1;
//                    q.push(nx);
//                }
                nx.str=rorate_str_180(tn.str,i);
                if(vis2.find(nx.str) == vis2.end()) {
                    vis2[nx.str] = 1;
                    nx.step = tn.step+1;
                    q.push(nx);
                }
//                num=str2int(nx.str);
//                if(!vis[num])
//                {
//                    vis[num]=1;
//                    nx.step=tn.step+1;
//                    q.push(nx);
//                }
                nx.str=rorate_str_270(tn.str,i);
                if(vis2.find(nx.str) == vis2.end()) {
                    vis2[nx.str] = 1;
                    nx.step = tn.step+1;
                    q.push(nx);
                }
//                num=str2int(nx.str);
//                if(!vis[num])
//                {
//                    vis[num]=1;
//                    nx.step=tn.step+1;
//                    q.push(nx);
//                }
            }

        }
        cout<<minx<<endl;
    }
    return 0;
}


 3.运行结果:


 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值