轉換地圖 (康託展開+預處理+BFS)

Problem Description

在小白成功的經過了第一輪面試後,他來到了第二輪面試。面試的題目有點難度了,爲了考覈你的思惟能量,面試官給你一副(2x4)的初態地圖,而後在給你一副(2x4)的終態地圖。每一幅地圖都是有數字1~8表示,給你的地圖的信息是一串序列,而後根據這序列,從地圖的左上角開始,按照順時針排列。 好比地圖信息爲12345678,則表示地圖:

1 2 3 4
8 7 6 5

對於這地圖有三種具體操做方式:

A: 上下兩行互換,如上圖可變換爲狀態87654321
B: 每行同時循環右移一格,如上圖可變換爲41236785
C: 中間4個方塊順時針旋轉一格,如上圖可變換爲17245368

根據所給的初狀地圖和終態地圖,請給出完成轉化的最少的變換步驟,如有多種變換方案則取字典序最小的那種。

Input

每組測試數據包括兩行,分別表明地圖信息的初態與終態。

Output

對於每次測試案例,輸出須要符合要求的變換步驟。

SampleInput

12345678
17245368
12345678
82754631

SampleOutput

C
AC

最開始預處理了一下直接搜,本地爆炸。
而後想到了用康託展開打個表,而後。。。就AC了。
這裏講一下康託展開算法
  X = An * (n-1)! + An-1 * (n-2)! + ... + A1 * 0!;
康拓展開就是求一個數字字符串在其全排列中的位置。
例如231這個數,全排列爲123 132 213 231 312 321
因此231排在第4位,那麼康託展開算法是如何求的呢。
例如求231的康託展開,從頭到尾依次判斷:
  1. 第一位數2,比2小的有一個,有1*2!
  2. 第二位數3,比3小的有兩個,但2已經出現,有1*1!
  3. 第三位數1,有0*0!

累加起來就是2 + 1 = 3,表示比231小的有3個,因此231排在第4位。node

代碼實現的話就是:ios

 

 1 int fac[] = {1,1,2,6,24,120,720,5040,40320};  //i的階乘
 2 int kangtuo(int n,char a[]){  //n表示1~n個數,a數組表示數字
 3     int i,j,t,res = 0;
 4     for(i = 0; i < n; i++){
 5         t = 0;
 6         for(j = i+1; j < n; j++)
 7             if(a[i] > a[j])
 8                 t++;
 9         res += t*fac[n-i-1];
10     }
11     return sum + 1;
12 }

知道了康託展開後,就能夠打表作了,值得一提的是這道題的預處理。由於題目輸入兩組字符串分別表示初始狀態和結束狀態,而咱們打表是從12345678到各個狀態的值,因此預處理咱們把輸入的初狀態轉成12345678,末狀態也執行相應轉換就能夠了;面試

代碼:算法

  1 #include <iostream>
  2 #include <string>
  3 #include <cstdio>
  4 #include <cstdlib>
  5 #include <sstream>
  6 #include <iomanip>
  7 #include <map>
  8 #include <stack>
  9 #include <deque>
 10 #include <queue>
 11 #include <vector>
 12 #include <set>
 13 #include <list>
 14 #include <cstring>
 15 #include <cctype>
 16 #include <algorithm>
 17 #include <iterator>
 18 #include <cmath>
 19 #include <bitset>
 20 #include <ctime>
 21 #include <fstream>
 22 #include <limits.h>
 23 #include <numeric>
 24 
 25 using namespace std;
 26 
 27 #define F first
 28 #define S second
 29 #define mian main
 30 #define ture true
 31 
 32 #define MAXN 1000000+5
 33 #define MOD 1000000007
 34 #define PI (acos(-1.0))
 35 #define EPS 1e-6
 36 #define MMT(s) memset(s, 0, sizeof s)
 37 typedef unsigned long long ull;
 38 typedef long long ll;
 39 typedef double db;
 40 typedef long double ldb;
 41 typedef stringstream sstm;
 42 const int INF = 0x3f3f3f3f;
 43 
 44 struct node{
 45     string str,step;
 46 };
 47 
 48 bool vis[40320+1];
 49 int  pos[10],fac[] = {1,1,2,6,24,120,720,5040,40320};
 50 string ans[41000];
 51 
 52 
 53 int fun(string a){
 54     int i,j,t,sum = 0;
 55     for(i = 0; i < 8; ++i){
 56         t = 0;
 57         for(j = i+1; j < 8; ++j)
 58             if(a[i] > a[j])
 59                 ++t;
 60         sum += t*fac[8-i-1];
 61     }
 62     return sum+1;
 63 }
 64 
 65 void ma(string &s){
 66     for(int i = 0; i < 4; ++i)
 67         swap(s[i],s[i+4]);
 68 }
 69 
 70 string mb(string s){
 71     string temp = s;
 72     for(int i = 0; i < 8; ++i){
 73         if(i==0 || i==4)
 74             temp[i]=s[i+3];
 75         else
 76             temp[i]=s[i-1];
 77     }
 78     return temp;
 79 }
 80 
 81 void mc(string &s){
 82     swap(s[1],s[2]);
 83     swap(s[5],s[6]);
 84     swap(s[1],s[6]);
 85 }
 86 
 87 void bfs( string s ){
 88     MMT(vis);
 89     queue<node>q;
 90     node pre,nxt;
 91 
 92     pre.str = s;
 93     pre.step = "";
 94     vis[fun(s)] = 1;
 95     ans[fun(s)] = pre.step;
 96     q.push(pre);
 97 
 98     while(!q.empty()){
 99         pre = q.front();
100         q.pop();
101 
102         nxt = pre;
103         ma(nxt.str);
104         if(!vis[fun(nxt.str)]){
105             nxt.step += "A";
106             vis[fun(nxt.str)] = 1;
107             ans[fun(nxt.str)] = nxt.step;
108             q.push(nxt);
109         }
110 
111         nxt.str = mb(pre.str);
112         if(!vis[fun(nxt.str)]){
113             nxt.step = pre.step + "B";
114             vis[fun(nxt.str)] = 1;
115             ans[fun(nxt.str)] = nxt.step;
116             q.push(nxt);
117         }
118 
119         nxt = pre;
120         mc(nxt.str);
121         if(!vis[fun(nxt.str)]){
122             nxt.step += "C";
123             vis[fun(nxt.str)] = 1;
124             ans[fun(nxt.str)] = nxt.step;
125             q.push(nxt);
126         }
127     }
128 }
129 
130 int main(){
131     ios_base::sync_with_stdio(false);
132     cout.tie(0);
133     cin.tie(0);
134     string s1,s2;
135     int k;
136     bfs("12345678");
137     //12345678
138     //17245368
139     //12345678
140     //82754631
141     while(cin>>s1>>s2){
142         swap(s1[4],s1[7]);
143         swap(s1[5],s1[6]);
144         swap(s2[4],s2[7]);
145         swap(s2[5],s2[6]);
146         for(int i = 0; i < 8; i++)
147             pos[s1[i]-'0'] = i+1;
148         for(int i = 0; i < 8; i++)
149             s2[i] = pos[s2[i]-'0'];
150         k = fun(s2);
151         cout<<ans[k]<<endl;
152     }
153     return 0;
154 }

其實康託展開也能夠求逆運算,具體思想以及代碼實現這裏就不講了=7=數組

相關文章
相關標籤/搜索