網易遊戲研發工程師筆試題
題目描述
小Q最近被邀請去參加了網易最牛大腦的節目,挑戰數字魔方的專案。
數字魔方為一個3x3的矩陣,矩陣中的每個數字都是(1…9)中的數字,且數字魔方中的數字可能重複。每4個相鄰的數字我們稱為1個子魔方,整個數字魔方共有4個子魔方(如下圖所示)。每一次操作可以選擇對某個子魔方順時針旋轉90度,180度或者270度。每個子魔方可以進行多次操作。
對子魔方1進行一次操作,順時針旋轉90度,180度,270度後的狀態:
專案的挑戰任務是,給定數字魔方的一個初始狀態,以及一個目標狀態,問最少操作多少次可以使得魔方從初始狀態改變為目標狀態。
小Q求助於你,希望你能告訴他完成任務的最少操作次數是多少,或者任務不可能完成。
輸入描述
輸入的第一行為一個正整數T(T<=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.執行結果: